博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
delta3d与ode物理引擎的结合。
阅读量:5143 次
发布时间:2019-06-13

本文共 7399 字,大约阅读时间需要 24 分钟。

      使用delta3d有些日子了,对物理引擎这块没有细看过,最近研究了一下。主要分为两大部分,第一在dtCore中对ode的封装,第二通过dtPhysics,使用PAL(phys abstract layer)对三种物理引擎 bullet、ode、phys的封装。

  这里先介绍下dtCore中对delta3d中的封装。总结起来就是如下几点:

    • dtCore::ODEWolrdWrap  主要是包装了ODE world的功能。这个类不是供用户直接使用的。
    • dtCore::ODESpaceWrap  主要包装了ODE space的功能,主要用于碰撞检测,这个类也不是直接给用户使用的。
    • dtCore::ODEController   这个类主要用于管理ODE 物理系统,提供注册物理对象,应用全局重力,迭代物理系统(包括碰撞检测和刚体动力)。提供一个默认的碰撞回调函数。里边引用了dtCore::ODEWolrdWrap和      dtCore::ODESpaceWrap这两个类。这个类主要是被dtCore::Scene类调用。
    • dtCore::ODEGeomWrap  这个类主要是包装了ODE Geom。主要被space用来进行碰撞检测。
    • dtCore::ODEBodyWrap  包装了ODE physics body。主要进行动力学的应用。
    • dtCore::Transformable   这个类是一切可移动物体的父类,里边引用了dtCore::ODEGemoWrap。如果想要设置用于碰撞检测的几何体(球,正方体等,)任何它的子类都可以设置。
    • dtCore::Physical  这个类引用了dtCore::ODEBodyWrap ,所以继承这个类的子类对象可以设置一个表现刚性物体的属性。并且这个类的父类是dtCore::Transformable,所以可以设置碰撞几何体来应用于碰撞检测和重力特性。
    • dtCore::Scene  场景类,引用了ODEController类,进行物理系统的管理。

关系大致就是这样,我就不画图表示了。

总之,在delta3D中应用ODE的时候,可以使用Scene类调用ODEController,通过ODEController中配置ODESpaceWrap,进行碰撞检测设置。因为Physical类中引用了ODEBodyWrap,所以他的子类可以进行动力学相关设置。

下面就上述的碰撞信息的数据流在delta3d中的代码中走一遍。

1、在scene的Scene::OnMessage(MessageData* data)方法中

1 if (data->message == dtCore::System::MESSAGE_PRE_FRAME)  2    {
3 double dt = *static_cast
(data->userData); 4 if (mImpl->mPhysicsController.valid()) 5 {
6 mImpl->mPhysicsController->Iterate(dt); 7 } 8 } 2、这个方法每帧都在监听,如果物理控制器有效的时候,就调用 9 ODEController::Iterate(double deltaFrameTime)进行遍历,如下 10 void dtCore::ODEController::Iterate(double deltaFrameTime) 11 {
12 double stepSize = deltaFrameTime; 13 14 // if step size is set, use it instead of the delta frame time 15 if (GetPhysicsStepSize() > 0.0) 16 {
17 stepSize = GetPhysicsStepSize(); 18 } 19 20 //calc the number of steps to take 21 const int numSteps = int(deltaFrameTime/stepSize); 22 23 TransformableVector::const_iterator it; 24 25 for (it = GetRegisteredCollidables().begin(); 26 it != GetRegisteredCollidables().end(); 27 ++it) 28 {
29 (*it)->PrePhysicsStepUpdate(); 30 } 31 32 for (int i=0; i
0.0) 40 {
41 Step(leftOver); 42 } 43 44 for (it = GetRegisteredCollidables().begin(); 45 it != GetRegisteredCollidables().end(); 46 ++it) 47 {
48 (*it)->PostPhysicsStepUpdate(); 49 } 50 }

3、在上一步中主要是调用ODEController中的Step函数进行碰撞处理。

如下:

1 void dtCore::ODEController::Step(double stepSize)  2 {
3 if (mMsgSender.valid()) 4 {
5 mMsgSender->SendMessage(ODEController::MESSAGE_PHYSICS_STEP, &stepSize); 6 } 7 8 if (mSpaceWrapper.valid()) { mSpaceWrapper->Collide(); } 9 10 if (mWorldWrapper.valid()) { mWorldWrapper->Step(stepSize); } 11 12 if (mSpaceWrapper.valid()) { mSpaceWrapper->PostCollide(); } 13 }

显然,就是先判断下是否存在发送者,存在的话就发送一个MESSAGE_PHYSICS_STEP(这个消息忘了在那进行处理了,见谅)的消息,就是起到调整物理时间步的。然后就调用sapce中的碰撞检测函数。

4、也就是如下代码:

1 void dtCore::ODESpaceWrap::Collide()  2 {
3 if (mUserNearCallback) 4 {
5 dSpaceCollide(mSpaceID, mUserNearCallbackData, mUserNearCallback); 6 } 7 else 8 {
9 dSpaceCollide(mSpaceID, this, DefaultNearCallback); 10 } 11 }

5、如果自己设置了碰撞函数,就调用自己的(scene中留有接口,可以直接设置碰撞检测函数),没有的话,就调用默认碰撞函数。

最终的碰撞检测函数如下:

View Code
1 void dtCore::ODESpaceWrap::DefaultNearCallback(void* data, dGeomID o1, dGeomID o2)  2 {
3 if (data == 0 || o1 == 0 || o2 == 0) 4 {
5 return; 6 } 7 8 ODESpaceWrap* spaceWrap = static_cast
(data); 9 10 Transformable* c1 = static_cast
(dGeomGetData(o1)); 11 Transformable* c2 = static_cast
(dGeomGetData(o2)); 12 13 dContactGeom contactGeoms[8]; 14 15 int numContacts = dCollide(o1, o2, 8, contactGeoms, sizeof(dContactGeom)); 16 17 if (numContacts > 0 && c1 != 0 && c2 != 0) 18 {
19 CollisionData cd; 20 21 cd.mBodies[0] = c1; 22 cd.mBodies[1] = c2; 23 24 cd.mLocation.set( 25 contactGeoms[0].pos[0], contactGeoms[0].pos[1], contactGeoms[0].pos[2] 26 ); 27 28 cd.mNormal.set( 29 contactGeoms[0].normal[0], contactGeoms[0].normal[1], contactGeoms[0].normal[2] 30 ); 31 32 cd.mDepth = contactGeoms[0].depth; 33 34 if (spaceWrap->mCollisionCBFunc.valid()) 35 {
36 spaceWrap->mCollisionCBFunc(cd); 37 } 38 39 if (c1 != 0 || c2 != 0) 40 {
41 dContact contact; 42 43 for (int i = 0; i < numContacts; ++i) 44 {
45 contact.surface.mode = dContactBounce; 46 contact.surface.mu = (dReal)1000.0; 47 contact.surface.bounce = (dReal)0.75; 48 contact.surface.bounce_vel = (dReal)0.001; 49 50 contact.geom = contactGeoms[i]; 51 52 // Make sure to call these both, because in the case of 53 // Trigger, meaningful stuff happens even if the return 54 // is false. 55 bool contactResult1 = c1->FilterContact(&contact, c2); 56 bool contactResult2 = c2->FilterContact(&contact, c1); 57 58 if (contactResult1 && contactResult2) 59 {
60 // All this also should be in a virtual function. 61 Physical* p1 = dynamic_cast
(c1); 62 Physical* p2 = dynamic_cast
(c2); 63 64 if (p1 != 0 || p2 != 0) 65 {
66 dJointID joint = dJointCreateContact(spaceWrap->mWorldWrapper->GetWorldID(), 67 spaceWrap->mContactJointGroupID, 68 &contact); 69 70 dJointAttach(joint, 71 p1 != 0 && p1->DynamicsEnabled() ? p1->GetBodyID() : 0, 72 p2 != 0 && p2->DynamicsEnabled() ? p2->GetBodyID() : 0); 73 } 74 } 75 } 76 } 77 } 78 }

6、上面说的是如何处理收到的数据,现在看一下如何把碰撞的数据发出去的,在ODEController的构造函数中,调用了一个函数

即Ctor(),这个函数的功能:如果发生碰撞,就是把碰撞时产生的数据发出去。

如下

1 void dtCore::ODEController::Ctor()  2 {
3 RefODE();//保证是原子操作 4 //supply our method to be called when geoms actually collide 5 mSpaceWrapper->SetDefaultCollisionCBFunc(dtCore::ODESpaceWrap::CollisionCBFunc(this, &ODEController::DefaultCBFunc)); 6 7 dSetMessageHandler(ODEMessageHandler); 8 dSetDebugHandler(ODEDebugHandler); 9 dSetErrorHandler(ODEErrorHandler); 10 } 11 然后调用相应的回调函数: 12 void dtCore::ODEController::DefaultCBFunc(const dtCore::ODESpaceWrap::CollisionData& data) 13 {
14 if (mMsgSender.valid()) 15 {
16 //have to convert to Scene::CollisionData for backward compatibility 17 dtCore::Scene::CollisionData scd; 18 scd.mBodies[0] = data.mBodies[0]; 19 scd.mBodies[1] = data.mBodies[1]; 20 scd.mDepth = data.mDepth; 21 scd.mLocation = data.mLocation; 22 scd.mNormal = data.mNormal; 23 24 //if a collision took place and we have a sender pointer, 25 //send out the "collision" message 26 mMsgSender->SendMessage(ODEController::MESSAGE_COLLISION, &scd);//把相关的数据发送出去了,这个消息可以在OnMessage()接收。 27 } 28 }

就是通过这样消息循环,把如何处理碰撞数据,如何在碰撞时添加相应的操作 联系起来。

以上就是dtCore对ODE的封装。

关于dtPhysics,等待研究明白,再补上。

顺便插个广告:delta3d技术交流qq群:12483772。欢迎加入!

转载于:https://www.cnblogs.com/kanego/archive/2011/12/09/2281730.html

你可能感兴趣的文章
itext jsp页面打印
查看>>
Perl正则表达式匹配
查看>>
DB Change
查看>>
nginx --rhel6.5
查看>>
Eclipse Python插件 PyDev
查看>>
selenium+python3模拟键盘实现粘贴、复制
查看>>
网站搭建(一)
查看>>
Spring JDBCTemplate
查看>>
Iroha and a Grid AtCoder - 1974(思维水题)
查看>>
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>
查询数据库锁
查看>>
我对于脚本程序的理解——百度轻应用有感
查看>>
面试时被问到的问题
查看>>
当前记录已被另一个用户锁定
查看>>
Node.js 连接 MySQL
查看>>
那些年,那些书
查看>>
注解小结
查看>>
java代码编译与C/C++代码编译的区别
查看>>