最近项目上需要用到物理仿真引擎,就找了这个BulletPhysics,不得不说,这玩意资料确实少!
下面简单的总结一下,入门须知!
1、Bullet下载与安装
简介: Bullet Physics是一个开源的物理引擎库,支持刚体、软体和碰撞检测等。它具有很好的库内容,并且已经在很多项目中成功应用。
- Github源码,(需要自己cmake编译):
- 网站: Bullet Real-Time Physics Simulation | Home of Bullet and PyBullet: physics simulation for games, visual effects, robotics and reinforcement learning.
https://pybullet.org/
- GitHub: GitHub - bulletphysics/bullet3: Bullet Physics SDK: real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc.Bullet Physics SDK: real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc. - GitHub - bulletphysics/bullet3: Bullet Physics SDK: real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc.
https://github.com/bulletphysics/bullet3
- 编译方法: bullet安装之——windows下的安装与VS开发_bullet3 windows-CSDN博客
https://blog.csdn.net/m0_43436602/article/details/104630520
- 【我是按照下面这个弄的,挺顺利】
- 网站: Bullet Real-Time Physics Simulation | Home of Bullet and PyBullet: physics simulation for games, visual effects, robotics and reinforcement learning.
2、辅助了解与使用指导:
- 很多想了解Bullet的人,应该都看过这个:
- Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)-CSDN博客
- 说的有点看不太懂,里面的有些没找到,不知道是不是下错了版本呢?但是可以辅助了解。
- 【API】网页文档:
- 【入门】下面这两篇也不错,但可惜没有继续更新了:
- 【中文使用文档】官方文档翻译:
3、与QT的一些交互
- 【模拟】Bullet主要是数据模拟,如果想真实的看到,需要一些辅助手段:
- 【OpenGL】略。。因为我自己也不太懂。
- 【PCL+VTK】如果只是想简要的看一下安装是否成功,以及相关静态刚体、动态刚体是否设置合理,可以用这个VTK来渲染看一下,帧率一般在20-30帧,反正不是很快;也有可能是我一直用updateCamera()进行更新导致的,但是VTKWidget嵌入QT的QWidget后,通过while循环调用spinOnce()不生效了,还没弄清为什么。。;
-
void MyVtkWidget::simuSphereDown() { //[Bullet模块] //世界的大小,从起点开始延申10km btVector3 worldAabbMin(-10000, -10000, -10000); btVector3 worldAabbMax(10000, 10000, 10000); int maxProxies = 1024;//本空间最大刚体数量,避免内存浪费 btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, maxProxies);//创建空间 //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));//设置重力方向,-9.801 //碰撞包围体 int nBallRadius = 1;//m btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), nBallRadius);//地面形状 btCollisionShape* fallShape = new btSphereShape(nBallRadius);//球体形状 //初始化地面(运动状态), //btQuaternion quaternion = btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 45.0f / 90.0f); //旋转轴,旋转弧度;绕轴旋转以最后一次为准,参数4:1表示无旋转 btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, -1*nBallRadius, 0))); //(质量,地表的惯性),固定不动的物体,质量是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;//质量,kg btVector3 fallInertia(0,0,0); fallShape->calculateLocalInertia(mass, fallInertia);//计算惯性 btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass, fallMotionState, fallShape, fallInertia);//质量、初始平台、运动对象、惯性 btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);//创建刚体球,动态刚体 dynamicsWorld->addRigidBody(fallRigidBody);//添加到世界 //【模拟测试】:从50m高往下落,记录高度变化 for (int i=0; i < 300; i++) { dynamicsWorld->stepSimulation(1/60.f,10); //模拟时间步长:每次模拟推进的时间量;1/60表示1s更新60次; //10表示模拟的最大子步数,物理引擎在一个时间步内分成多个子步进行模拟; btTransform trans; fallRigidBody->getMotionState()->getWorldTransform(trans);//获取变换后的位置 PointT point; std::cout << "sphere X: " << trans.getOrigin().getX() << ", Y(height): " << trans.getOrigin().getY() << ", Z: " << trans.getOrigin().getZ() <<std::endl; point.x = trans.getOrigin().getX(); point.y = trans.getOrigin().getY(); point.z = trans.getOrigin().getZ(); m_lstPoint.push_back(point); } 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; }
-
- 【VTK演示】
4、总结
- 比较早期的基础学习,可以一点一点的设置,后续多看库的源码会发现,它其实已经把一些初始化函数做好了,我们要做的就是继承类,然后重写一些函数;
- 类似:
#include "btBulletDynamicsCommon.h" #include "LinearMath/btVector3.h" #include "LinearMath/btAlignedObjectArray.h" #include "CommonInterfaces/CommonRigidBodyBase.h" class BasicExample : public QObject, public CommonRigidBodyBase { …//重写一些东西 … }
// 设置上方向 m_guiHelper->setUpAxis(1); // 创建空的动力学世界 createEmptyDynamicsWorld(); // 创建物理调试绘制 m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); // 设置物理调试绘制模式 if (m_dynamicsWorld->getDebugDrawer()) m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe + btIDebugDraw::DBG_DrawContactPoints);
btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), 0.05); m_collisionShapes.push_back(groundShape);//添加到刚体形状数组中 btTransform groundTransform; groundTransform.setIdentity();//设置为单位矩阵 groundTransform.setOrigin(btVector3(0, -0.05, 0)); { btScalar mass(0.);//btScalar就是小数,静态刚体质量为0 auto rigid = createRigidBody(mass, groundTransform, groundShape, btVector4(0, 0, 0, 1));//此方法会自动添加刚体到物理世界 rigid->setFriction(0.5);//摩擦系数,取均值 rigid->setRestitution(0.0);//弹性系数 rigid->setRollingFriction(0.3);//滚动摩擦系数 m_vRigid.append(rigid); }
- 类似:
- 总的来说,入门多看几遍例子就行,后续多看源码就好,还是蛮有意思的,就是资料不太多。