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中的应用的更多相关文章

  1. bullet物理引擎与OpenGL结合 导入3D模型进行碰撞检测 以及画三角网格的坑

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11681069.html 一.初始化世界以及模型 /// 冲突配置包含内存的默认设置,冲突设置. ...

  2. Bullet物理引擎的安装与使用

    图形赋予游戏一种视觉的吸引力,但是能够让游戏的世界鲜活起来的还应该是内部的物理引擎.物理引擎是游戏引擎中的子模块,是一种软件组件,可仿真物理系统.它根据牛顿力学定律,计算游戏中物体的合理的物理位置,并 ...

  3. 将 Android* Bullet 物理引擎移植至英特尔&#174; 架构

    简单介绍 因为眼下的移动设备上可以使用更高的计算性能.移动游戏如今也可以提供震撼的画面和真实物理(realistic physics). 枪战游戏中的手雷爆炸效果和赛车模拟器中的汽车漂移效果等便是由物 ...

  4. 转:Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)

    write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 前言 Bullet据称为游戏世界占有率为第三的物理引擎,也是前几大引擎目前唯一能够 ...

  5. 【Bullet引擎】Bullet物理引擎简单说明

    说明 Bullet是一款开源的物理模拟计算引擎,包括刚体.柔体.弹性体等,是世界三大物理模拟引擎之一(包括Havok和PhysX),被广泛应用于游戏开发(GTA5等)和电影(2012等)制作中. Bu ...

  6. 链接收藏:bullet物理引擎不完全指南

    这个也是博客园的文章,编辑得也很好,就不copy了,结尾还有PDF: https://www.cnblogs.com/skyofbitbit/p/4128347.html 完结

  7. cocos2d-x中的Box2D物理引擎

    在Cocos2d-x中集成了2个物理引擎,一个是Chipmunk,一个是Box2D.前者是用C语言编写的,文档和例子相对较少:Box2D是用C++写的,并且有比较完善的文档和资料.所以在需要使用物理引 ...

  8. 【AwayPhysics学习笔记】:Away3D物理引擎的简介与使用

    首先我们要了解的是AwayPhysics这个物理引擎并不是重头开始写的新物理引擎,而是使用Flascc技术把一个已经很成熟的Bullet物理引擎引入到了Flash中,同时为了让as3可以使用这个C++ ...

  9. 【Unity 3D】学习笔记三十六:物理引擎——刚体

    物理引擎就是游戏中模拟真是的物理效果.如两个物体发生碰撞,物体自由落体等.在unity中使用的是NVIDIA的physX,它渲染的游戏画面很逼真. 刚体 刚体是一个很很中要的组件. 默认情况下,新创的 ...

随机推荐

  1. Xcode Custom Shortcut

    edit file "/Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Resources" add < ...

  2. 添加了有道生词本的 chrome google翻译扩展和有道翻译扩展

    在chrome发布项目,需要先花美金认证,还得要美国ID,无奈. 直接上源码,需手动导入. 原始项目源码并未开源,个人是从chrome本地文件里拿出来的,拓展来的,侵删(本来想着自已写一个,业余时间, ...

  3. android 使用LinearGradient进行字体渐变的效果

    有这么一种效果,一串字符有一束白光从字体上面闪光的效果.如下图显示: 就像上面的显示效果一样一束白光闪过,这种效果主要还是使用了LinearGradient类来进行的 LinearGradient也称 ...

  4. Linux内核【链表】整理笔记(1)

    我们都知道Linux内核里的双向链表和学校里教给我们的那种数据结构还是些不一样.Linux采用了一种更通用的设计,将链表以及其相关操作函数从数据本身进行剥离,这样我们在使用链表的时候就不用自己去实现诸 ...

  5. Windows cmd命令搜索顺序

    一.在cmd中执行一个不带后缀的命令(不带路径),首先会在无后缀的系统命令(如cd.dir等)中搜索,如果找到了就执行该命令, (dir是无后缀的系统命令所以优先执行,无视当前目录中的dir.exe) ...

  6. 学习总结relative和absolute

    之前对于absolute和relative不了解,现在整理 先设置relative再设置absolute 因为父不设置relative 那么子会向上寻找祖先元素,看是否设置relative.如果有则相 ...

  7. python hashlib模块

    用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 import hashlib m=hash ...

  8. oracle flashback功能

    2). 检查Flashback 功能, 缺省时功能是关闭的. SQL> select name, current_scn, flashback_on from v$database; NAME  ...

  9. H5前端性能测试快速入门

    前言 说到H5测试,对于做WEB测试的同学来说再熟悉不过了,它包括页H5功能测试,前端性能测试,浏览器兼容性能测试,以及服务端性能测试.那本文谈到的则是H5前端性能测试,并希望通过阅读本文后,能够知道 ...

  10. 使用自定义的framework

    1.创建framework工程,创建需要的类将接口暴露在public中