Bullet物理引擎在OpenGL中的应用
来源:互联网 发布:vm安装linux虚拟机 编辑:程序博客网 时间:2024/05/16 05:46
Bullet物理引擎在OpenGL中的应用
在开发OpenGL的应用之时, 难免要遇到使用物理来模拟OpenGL中的场景内容. 由于OpenGL仅仅是一个关于图形的开发接口, 因此需要通过第三方库来实现场景的物理模拟. 目前我选择 Bullet 物理引擎, 其官方网站为Bullet, 开发库的下载地址则在github 上.
1. OpenGL 环境
首先我们需要搭建框架, OpenGL 的基本框架这里不详述, 我个人是在几何着色器内实现光照, 这是由于我实现的是面法线. 另外用到的其他三方库有 GLFW 和 GLM库, 前者有助于管理OpenGL窗口, 后者省却了自己写数学公式代码的过程. 另外实现了立方体模型和球体的创建, 满足学习 Bullet 的需要即可.
2. 物理环境的初始化
对于 Bullet 物理库而言, 它的搭建也很简单, 在初始化 OpenGL 的上下文的时候, 也可以初始化我们的物理环境, 参考物理库自带的 HelloWorld 即可, 相关代码为:
///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new btDefaultCollisionConfiguration(); //m_collisionConfiguration->setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; m_solver = sol; m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
3. 物理环境的销毁
相应的, 还有清理代码
std::vector<ModelInfo>::iterator it = m_models.begin(); while(it != m_models.end()) { ModelInfo info = *it; delete info.model; m_dynamicsWorld->removeRigidBody(info.obj); it++; } m_models.clear(); for (int j=0;j<m_collisionShapes.size();j++) { btCollisionShape* shape = m_collisionShapes[j]; m_collisionShapes[j] = 0; delete shape; } //delete dynamics world delete m_dynamicsWorld; //delete solver delete m_solver; delete m_broadphase; delete m_dispatcher; delete m_collisionConfiguration; //next line is optional: it will be cleared by the destructor when the array goes out of scope m_collisionShapes.clear();
在我的实现内, 结构体 ModelInfo 是一个自定义的结构体(struct), 我通过该结构体的容器保存了所有物体的物理模型以及其对应OpenGL模型的关系, 这样在物理库更新一个物体的位置和方向时, 我们就可以在 OpenGL 内更新物体的位置和方向.
4. 物理世界的渲染
下面是我渲染物理世界中所有模型的代码, 计算出所有模型的变换矩阵, 而后通知其相关代码进行渲染.
void PhysicsBaseWorld::render(){ std::vector<ModelInfo>::iterator it = m_models.begin(); while(it != m_models.end()) { ModelInfo info = *it; btRigidBody* obj = info.obj; btRigidBody* body = btRigidBody::upcast(obj); btTransform trans; if (body && body->getMotionState()) { body->getMotionState()->getWorldTransform(trans); } else { trans = obj->getWorldTransform(); } glm::vec3 position = glm::vec3(float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ())); btQuaternion rot = trans.getRotation(); glm::quat q = glm::quat(rot.getW(), rot.getX(), rot.getY(), rot.getZ()); glm::mat4 rot4 = glm::toMat4(q); glm::mat4 m = glm::translate(glm::mat4(1.0), position) * rot4; Model* model = info.model; model->setModelMat(m); model->render(); it++; }}
5. 绘制静态的物体
在创建物理世界的过程中, 物理库中主要使用函数 createRigidBody() 来创建刚体模型, 其主要有三个参数, 分别表示质量, 变换, 形状. 其中质量为 0 的物体为静止物体, 可以用来创建地面或者路边的石头之类的物体模型. 创建静止立方体模型的代码
///create a few basic rigid bodies btCollisionShape* shape = new btBoxShape(btVector3(halfsize[0],halfsize[1],halfsize[2])); m_collisionShapes.push_back(shape); btTransform transform; transform.setIdentity(); transform.setOrigin(btVector3(pos[0], pos[1], pos[2])); { btScalar mass(0.); btRigidBody* body = createRigidBody(mass,transform,shape); Cube* cube = new Cube(halfsize[0],halfsize[1],halfsize[2]); cube->setColor(col); ModelInfo info = {body, cube}; m_models.push_back(info); }
上面的代码创建的过程中, 我同时创建了一个对应的 OpenGL 立方体.
6. 绘制可活动的物体
创建可活动模型时需要设置相关的运动状态信息
btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE)); //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) shape->calculateLocalInertia(mass, localInertia); btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape, localInertia); btRigidBody* body = new btRigidBody(cInfo); body->setUserIndex(-1); m_dynamicsWorld->addRigidBody(body); btBoxShape* s = dynamic_cast<btBoxShape*>(shape); if(s != 0) { btVector3 size = s->getHalfExtentsWithMargin(); Cube* cube = new Cube(size.getX(), size.getY(), size.getZ()); cube->setColor(col); ModelInfo info = {body, cube}; m_models.push_back(info); } return body;
7. 更新物理世界
最后我们需要时刻更新物理世界中的模型位置和方位
m_dynamicsWorld->stepSimulation(elpasedTime, 0);
- Bullet物理引擎在OpenGL中的应用
- Bullet 物理引擎 简析
- bullet物理引擎-配置
- Bullet 物理引擎 简析[1]
- Bullet 物理引擎 简析[1]
- Bullet物理引擎及基础知识
- Bullet物理引擎教程: helloworld
- bullet物理引擎创建流程
- 【转】p2物理引擎在egret中的应用
- Bullet 3D 物理引擎 简析(2)
- Bullet 物理引擎 详细分析 Dbvt (2)
- Bullet 物理引擎 详细分析 Dbvt (3)
- Bullet 物理引擎 详细分析 Dbvt (4)
- Bullet 3D 物理引擎 简析(2)
- Bullet 物理引擎 详细分析 Dbvt (2)
- iOS 中引入Bullet 物理引擎
- Bullet物理引擎不完全指南 in Linux
- 给osg配置bullet物理引擎
- Handler消息机制之基础代码运用篇(3)
- 动态获取打包Jar后的路径信息
- 216. Combination Sum III
- Handler机制在秒表中的运用
- SlidingPaneLayout、Navigation Drawer、drawerlayout
- Bullet物理引擎在OpenGL中的应用
- 我是刘杰,欢迎参观我的博客
- hdu1061(快速幂取余)
- Android ImageSlider实现广告轮播
- json-schema-core(liuhailong翻译)
- [leetcode] 276. Paint Fence 解题报告
- 扫扫土,开工啦~
- docker+node+Cordova 多平台流媒体直播系统 一 centos6.5 源码编译安装node5.8(1)
- [leetcode] 288. Unique Word Abbreviation 解题报告