Bullet物理引擎在OpenGL中的应用
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物理引擎与OpenGL结合 导入3D模型进行碰撞检测 以及画三角网格的坑
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11681069.html 一.初始化世界以及模型 /// 冲突配置包含内存的默认设置,冲突设置. ...
- Bullet物理引擎的安装与使用
图形赋予游戏一种视觉的吸引力,但是能够让游戏的世界鲜活起来的还应该是内部的物理引擎.物理引擎是游戏引擎中的子模块,是一种软件组件,可仿真物理系统.它根据牛顿力学定律,计算游戏中物体的合理的物理位置,并 ...
- 将 Android* Bullet 物理引擎移植至英特尔® 架构
简单介绍 因为眼下的移动设备上可以使用更高的计算性能.移动游戏如今也可以提供震撼的画面和真实物理(realistic physics). 枪战游戏中的手雷爆炸效果和赛车模拟器中的汽车漂移效果等便是由物 ...
- 转:Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 前言 Bullet据称为游戏世界占有率为第三的物理引擎,也是前几大引擎目前唯一能够 ...
- 【Bullet引擎】Bullet物理引擎简单说明
说明 Bullet是一款开源的物理模拟计算引擎,包括刚体.柔体.弹性体等,是世界三大物理模拟引擎之一(包括Havok和PhysX),被广泛应用于游戏开发(GTA5等)和电影(2012等)制作中. Bu ...
- 链接收藏:bullet物理引擎不完全指南
这个也是博客园的文章,编辑得也很好,就不copy了,结尾还有PDF: https://www.cnblogs.com/skyofbitbit/p/4128347.html 完结
- cocos2d-x中的Box2D物理引擎
在Cocos2d-x中集成了2个物理引擎,一个是Chipmunk,一个是Box2D.前者是用C语言编写的,文档和例子相对较少:Box2D是用C++写的,并且有比较完善的文档和资料.所以在需要使用物理引 ...
- 【AwayPhysics学习笔记】:Away3D物理引擎的简介与使用
首先我们要了解的是AwayPhysics这个物理引擎并不是重头开始写的新物理引擎,而是使用Flascc技术把一个已经很成熟的Bullet物理引擎引入到了Flash中,同时为了让as3可以使用这个C++ ...
- 【Unity 3D】学习笔记三十六:物理引擎——刚体
物理引擎就是游戏中模拟真是的物理效果.如两个物体发生碰撞,物体自由落体等.在unity中使用的是NVIDIA的physX,它渲染的游戏画面很逼真. 刚体 刚体是一个很很中要的组件. 默认情况下,新创的 ...
随机推荐
- Android环境配置及运行helloWord案例
Android的环境搭建步骤,以及输出一个helloWorder 1:下载Android开发环境 及是: SDK adt-bundle-windows-x86_64-20140702 此时的版 ...
- RancherOS Hyper-V 安装
RancherOS Hyper-V 安装, Install to disk 打开 Hyper-V 管理界器, 新建虚拟机 输入名称和存储位置 选择一代 最低 1024M 配置网络 创建虚拟磁盘 设置启 ...
- POJ 1149PIGS 网络流 最大流
PIGS Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20421 Accepted: 9320 Description ...
- iOS开发时,在Xcode中添加多个Targets进行版本控制
在iOS开发中,很可能有以下场景:需要开发多个版本,或因需区分收费版,免费版,或因为网络环境需要区分测试版,发布版,或因渠道不同需要区分企业版,AppStore版等等.解决办法无非就是CheckOut ...
- SVN常用问题汇总
参考文档.http://www.cnblogs.com/newsea/archive/2012/04/28/2474818.html 1.客户端取消记住用户名和密码. 2.汉化后设置为中文
- javascript学习面向对象(二)
主要内容: prototype扩展应用示例: 对比如下: 数组中forEach用法示例: 从上面示例可以看出,forEach只适合遍历一维数组: 应用prototype扩展实现全部元素遍历如下: 简单 ...
- Ubuntu 14.04 更新源
deb http://mirrors.163.com/ubuntu/ trusty main restricted universe multiversedeb http://mirrors.163. ...
- Unity3D安卓打包参数配置与兼容性的关系分析
前言 在使用Unity3D工程导出安卓安装包的时候,往往会遇到兼容性的问题,针对某些机型,要么无法打开游戏,要么会出现卡机的现象.面对这种情况,我们可以调节相关的参数来提高兼容性. 为了了解在打包时候 ...
- javaweb中实现在线人数统计
session并不是浏览器关闭时销毁的,而是在session失效的时候销毁下列代码就是监测session创建.销毁 package com.my.count; import javax.servlet ...
- java抽象语法
1.基本概念: 0.0.抽象类的定义:抽象类是为子类提供一个规范,其目地是由子类去继承实现(类似国家提出的法律,由我们去执行). 0.1.定义抽象类用abstract来定义. 语法: public a ...