Bullet入门使用,三维碰撞检测

本文介绍了BulletPhysics物理引擎的下载与安装方法,包括Windows下的CMake编译步骤,并提供了VS环境下的配置教程和基本使用案例,还讨论了与QT和OpenGL的交互,以及如何通过VTK进行初步模拟测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近项目上需要用到物理仿真引擎,就找了这个BulletPhysics,不得不说,这玩意资料确实少!

下面简单的总结一下,入门须知!

1、Bullet下载与安装

简介: Bullet Physics是一个开源的物理引擎库,支持刚体、软体和碰撞检测等。它具有很好的库内容,并且已经在很多项目中成功应用。

2、辅助了解与使用指导:

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);
          }
  • 总的来说,入门多看几遍例子就行,后续多看源码就好,还是蛮有意思的,就是资料不太多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值