Qt Quick + OpenGL + Bullet初次測试

眼下Qt的Quick模块已经表现得很出色,并且可以预留接口来渲染OpenGL场景。一般来说,已经可以满足大部分编程须要了。这次呢。尝试使用结合一些技术,来做一些有趣儿的事情——将Bullet整合进来,并且进行測试。

蒋彩阳原创文章。首发地址:http://blog.csdn.net/gamesdev/article/details/44284317。欢迎同行前来探讨。

有关Bullet的选择,事实上也是有一番讲究的。眼下Bullet的2.82版本号,临时没有更新了,而Bullet 3.x。则是还少有应用。假设我们去看Bullet的新的代码库——github。就会发现,在“Requirementsfor Bullet 2”,作者表示差点儿不论什么编译器都可以编译它的代码,而在“Requirements
for Bullet 3”的介绍中,仅仅是说能在高端的显卡中执行,低端显卡或者是移动设备可能和Bullet 3无缘了。

所以在这样的情况下,我就选择Bullet 2.82来制作这个样例。

为了完毕这个样例,我參考了前辈们的一些样例,比方说Qt在诺基亚时期,就写了一个非常棒的Bullet + Qt的样例。叫做BulletDice。

它的github地址在这里。这边儿比較简单,easy上手。再加上Bullet有一份Manual,两者结合起来看。方便了很多。

花了一周的时间。最终模仿而且制作出来了这种效果:

一開始立方体在平面的上面位置,随后依据重力,呈自由落体速度,慢慢地往下落。

终于落在了地面上。下图表示落下来时候的样子:

怎么样?非常easy吧。

这里也是我对Bullet的初步认识。在编写这个样例的过程中,遇到了非常多困难,也有非常多地方值得推敲。

所以我在这里先作一个笔记。给以后作參考。

首先为了验证物理引擎可用,我在类中写了一个函数叫debugShow()。每次仿真採样的时候。输出立方体的位置。在验证这样是没有问题的基础上。開始研究如何让数据与渲染相结合。以下的代码片描写叙述了与Bullet相关的一些知识:

void DynamicsWorldPrivate::initializePhysics( void )
{
// 初始化物理引擎
m_broadPhase = new btDbvtBroadphase;
m_conf = new btDefaultCollisionConfiguration;
m_dispatcher = new btCollisionDispatcher( m_conf );
m_solver = new btSequentialImpulseConstraintSolver; // 应用重力
m_world = new btDiscreteDynamicsWorld( m_dispatcher,
m_broadPhase,
m_solver,
m_conf );
m_world->setGravity( btVector3( 0, -9.81, 0 ) ); // 创建一个平面刚体
createPlane( ); // 创建一个立方体刚体
createCube( );
} void DynamicsWorldPrivate::releasePhysics( void )
{
delete m_world; m_world = Q_NULLPTR;
delete m_solver; m_solver = Q_NULLPTR;
delete m_conf; m_conf = Q_NULLPTR;
delete m_dispatcher; m_dispatcher = Q_NULLPTR;
delete m_broadPhase; m_broadPhase = Q_NULLPTR; qDeleteAll( m_shapes );
qDeleteAll( m_bodies );
m_shapes.clear( );
m_bodies.clear( );
} void DynamicsWorldPrivate::createPlane( void )
{
btStaticPlaneShape* planeShape = new btStaticPlaneShape(
btVector3( 0, 1, 0 ), // 平面法线
0.0 ); // 平面的相对原点的距离 btTransform originTransform;
originTransform.setFromOpenGLMatrix( m_planeModelMatrix->data( ) );
btDefaultMotionState* motionState = new btDefaultMotionState(
originTransform, // 開始的变换
btTransform::getIdentity( ) ); // 中心平移量 btRigidBody::btRigidBodyConstructionInfo planeInfo(
0, // 质量
motionState, // 运动状态
planeShape, // 碰撞的形状
btVector3( 0, 0, 0 ) ); // 本地的惯性
m_planeBody = new btRigidBody( planeInfo );
m_world->addRigidBody( m_planeBody );
m_shapes.append( planeShape );
m_bodies.append( m_planeBody );
} void DynamicsWorldPrivate::createCube( void )
{
qreal semi = m_cubeLength / 2.0;
btBoxShape* cubeShape = new btBoxShape(
btVector3( semi, semi, semi ) );// 半个立方体的大小 btTransform originTransform;
originTransform.setFromOpenGLMatrix( m_cubeModelMatrix->data( ) ); btDefaultMotionState* motionState = new btDefaultMotionState(
originTransform, // 開始的变换
btTransform::getIdentity( ) ); // 中心平移量 btRigidBody::btRigidBodyConstructionInfo cubeInfo(
0.8f, // 质量
motionState, // 运动状态
cubeShape, // 碰撞的形状
btVector3( 0, 0, 0 ) ); // 本地的惯性
cubeInfo.m_friction = 0.3; // 摩擦力
cubeInfo.m_restitution = 0.1; // 反弹力(恢复力) m_cubeBody = new btRigidBody( cubeInfo );
m_world->addRigidBody( m_cubeBody );
m_shapes.append( cubeShape );
m_bodies.append( m_cubeBody );
} void DynamicsWorldPrivate::simulate( void )
{
QTime curTime = QTime::currentTime( );
int stepTime = m_lastTime.msecsTo( curTime );
m_lastTime = curTime; m_world->stepSimulation( btScalar( stepTime ) * 0.001 );
} void DynamicsWorldPrivate::debugShow( void )
{
btTransform worldTransform;
m_cubeBody->getMotionState( )->getWorldTransform( worldTransform );
btVector3 position = worldTransform * btVector3( 0, 0, 0 );
qDebug( "position is: ( %.2f, %.2f, %.2f )",
position.x( ), position.y( ), position.z( ) );
}

随后,可能要考虑,在这个模型中,仅仅有一个施力物体。也就是“地球”,它对立方体施以重力。让立方体做自由落体运动,运动过程中採样的轨迹通过body中motionState中的worldTransform来表述。假设和渲染引擎相结合的话,我这边的做法是物理引擎终于仅仅改动物体的modelMatrix,模型自己的形态则控制着本原位置,摄像机的參数控制着viewMatrix和projectionMatrix。

仅仅有这样。一切看起来概念才清晰。

这里可能有一个比較棘手的问题,有时候,须要对modelMatrix进行手动控制,来改变模型的变换信息。可是呢。modelMatrix又是受物理引擎控制的。所以对于modelMatrix受手动控制和物理引擎控制的切换,是比較难以处理的,下次我再看看随着学习的深入,能不能厘清他们之前的关系。

最后。我也在我的Android平板电脑上測试成功。

说明Bullet是全然能够做到结合Qt来跨平台的。

Qt Quick + OpenGL + Bullet初次測试的更多相关文章

  1. 局域网网络性能測试方法HDtune 64K有缓存測速法,让你得知你的网络性能

    该方法能够有效測试出您的网络传输性能究竟有多高,该方法通用于有盘,无盘(系统虚拟盘) ,游戏虚拟盘,以及其它带有缓存功能的虚拟盘软件,可是由于每款软件的工作方式和原理都不仅同样,所以每款软件的測试结果 ...

  2. OpenGL学习脚印:深度測试(depth testing)

    写在前面 上一节我们使用AssImp载入了3d模型,效果已经令人激动了.可是绘制效率和场景真实感还存在不足,接下来我们还是要保持耐心,继续学习一些高级主题,等学完后面的高级主题,我们再次来改进我们载入 ...

  3. Mali GPU OpenGL ES 应用性能优化--測试+定位+优化流程

    1. 使用DS-5 Streamline定位瓶颈 DS-5 Streamline要求GPU驱动启用性能測试,在Mali GPU驱动中激活性能測试对性能影响微不足道. 1.1 DS-5 Streamli ...

  4. Android +NDK+eclipse+opengl ES2.0 开启深度測试

    參考:https://www.opengl.org/discussion_boards/showthread.php/172736-OpenGL-ES-Depth-Buffer-Problem 环境: ...

  5. 浏览器上的Qt Quick

    你想不想在浏览器上运行你的Qt Quick程序呢?在Qt 5.12之前,唯一的方法是使用Qt WebGL Streaming技术把界面镜像到浏览器上.但该方法有不少缺陷,下文会说.前不久随着Qt 5. ...

  6. 从头学Qt Quick(1) --体验快速构建动态效果界面

    自2005年Qt4发布以来,Qt已经为成千上万的应用程序提供了框架服务,现在Qt已经基本上支持所有的开发平台了,这里面既包含了桌面.嵌入式领域,也包括了Android.IOS.WP等移动操作平台,甚至 ...

  7. Qt Quick实现的涂鸦程序

    之前一直以为 Qt Quick 里 Canvas 才干够自绘.后来发觉不是,原来还有好几种方式都能够画图! 能够使用原始的 OpenGL(Qt Quick 使用 OpenGL 渲染).能够构造QSGN ...

  8. Qt Quick 与 QML语言(初学笔记1)

    Qt Quick Qt Quick是一些新的UI技术的集合,用来帮助开发者创建一种现在越来越多用于手机.多媒体播放器.机顶盒以及其他便携式设备上的直观的.现代的.流畅的用户界面.简单来说,Qt Qui ...

  9. Qt Quick 布局演示

    于 Qt Widgets 于,我们经常使用许多布局管理器来管理界面 widgets . 于 Qt Quick 实际上,有两个相关的管理和布局库,所谓集 Item Positioner ,所谓集 Ite ...

随机推荐

  1. Discuz常见大问题-如何在自定义页面使用首页四格

    根据要求把majianjun文件夹放到指定目录 在DIY模式下点击保存后面的小按钮,然后导入XML文件 默认是采集所有版块的数据,你可以保存之后再次DIY,然后设置数据来源和设置标题等信息. 需要注意 ...

  2. UITableViewAutomaticDimension

    tableView.rowHeight = UITableViewAUtomaticDimension UITableViewAutomaticDimension is the default val ...

  3. Java从零开始学三十八(JAVA IO- 重定向IO)

    一.三个静态变量 java.lang.System提供了三个静态变量 System.in(默认键盘) System.out(默认显示器) System.err 二.重写向方法 System提供了三个重 ...

  4. Python3.2官方文档翻译--标准库概览(一)

    7.1 操作系统接口 Os模块提供主要很多与操作系统交互的函数. >>> import os >>> os.getcwd() # Return the curren ...

  5. EasyMock的使用

    1.Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开.同时也可以当调用别人的模块,而该模块又没有实现时(只提供 ...

  6. 20个常用java代码段

    下面是20个非常有用的Java程序片段,希望能对你有用. 1. 字符串有整型的相互转换 String a = String.valueOf(2); //integer to numeric strin ...

  7. ipa 打包遇到的坑

    1.xcode 打包 并上传至 appstore 审核 2.预留邮箱 收取 appstore 的审核结果 3.审核通过以后,通过 iTunes Connect 上传正式文件至 appstore     ...

  8. linux 使用wc命令统计文件行数、字数及大小

    语法:wc [选项] 文件… 说明:该命令统计给定文件中的字节数.字数.行数.如果没有给出文件名,则从标准输入读取.wc同时也给出所有指定文件的总统计数.字是由空格字符区分开的最大字符串. 该命令各选 ...

  9. flume的memeryChannel中transactionCapacity和sink的batchsize需要注意事项

    一. fluem中出现,transactionCapacity查询一下,得出一下这些: 最近在做flume的实时日志收集,用flume默认的配置后,发现不是完全实时的,于是看了一下,原来是memery ...

  10. nodejs实现拉钩网爬虫

    概述 通过nodejs+mysql+cheerio+request实现拉钩网特定公司的所有招聘信息的抓取,并将抓取的信息保存到数据库中.抓取内容包括:薪酬福利,工作地,职位要求,工作性质等几乎所有的内 ...