Bullet Physics Engine(物理引擎)中使用约束
来源:互联网 发布:淘宝瑕疵大牌化妆品 编辑:程序博客网 时间:2024/05/17 00:16
Bullet(version 2.77)中提供了6中基本的约束:
- 点点约束 btPoint2PointConstraint
- 铰链约束 btHingeConstraint
- 滑动约束 btSliderConstraint
- 锥形约束 btConeTwistConstraint
- 通用的6自由度约束 btGeneric6DofConstraint
- 接触点约束 btContactConstraint
全部继承自btTypedConstraint。
前4个约束在使用上都比较简单,其功能也容易顾名思义,可以参考SDK带的例子ConstraintDemo。
btGeneric6DofConstraint的6自由度分别是表示平移的3个分量和表示旋转的欧拉角的3个分量,欧拉角使用Roll-Yaw-Pitch的旋转顺序,即相当于对X的旋转矩阵Y的旋转矩阵Z的旋转矩阵的复合。
(欧拉角:http://www.cnitblog.com/luckydmz/archive/2010/09/07/68674.html)
btContactConstraint貌似是一个已经被废弃的约束,现在并没有被使用,而且实现是空的。
在btSequentialImpulseConstraintSolver中将碰撞信息创建成了btSolverConstraint,而它没有继承自btTypedConstraint。
接下来主要讨论btGeneric6DofConstraint的用法及其使用上的限制和绕过限制的方法。
先看一个简单的例子:
btVector3 pivotInA(0,5,0);
btTransform trans(btTransform::getIdentity());
trans.setOrigin(pivotInA);
btTypedConstraint* p2p = new btGeneric6DofConstraint(*body0, trans, true);
这段代码使用btGeneric6DofConstraint创建了一个点点约束,body0被约束到保持到它上方5个单位处的定点的距离不变,而可以绕该定点任意旋转。btTransform trans(btTransform::getIdentity());
trans.setOrigin(pivotInA);
btTypedConstraint* p2p = new btGeneric6DofConstraint(*body0, trans, true);
相当于等价的用btPoint2PointConstraint创建出的如下约束:
btVector3 pivotInA(0,5,0);
btTypedConstraint* p2p = new btPoint2PointConstraint(*body0, pivotInA);
上例中btGeneric6DofConstraint的构造函数参数的意义如下:btTypedConstraint* p2p = new btPoint2PointConstraint(*body0, pivotInA);
btGeneric6DofConstraint(
btRigidBody& rbB, //被约束的刚体
const btTransform& frameInB, //对约束刚体的变换,约束条件是建立在变换后的刚体上
bool useLinearReferenceFrameB); //true表示约束条件参考由frameInB定义的坐标系否则参考世界坐标系
在创建出btGeneric6DofConstraint之后还应该使用如下函数设置6个自由度的约束条件
void setLinearLowerLimit(const btVector3& linearLower);
void setLinearUpperLimit(const btVector3& linearUpper);
void setAngularLowerLimit(const btVector3& angularLower);
void setAngularUpperLimit(const btVector3& angularUpper);
Lowerlimit == Upperlimit -> axis is locked. void setLinearUpperLimit(const btVector3& linearUpper);
void setAngularLowerLimit(const btVector3& angularLower);
void setAngularUpperLimit(const btVector3& angularUpper);
Lowerlimit > Upperlimit -> axis is free
Lowerlimit < Upperlimit -> axis it limited in that range
如果不设置约束条件,默认情况平移将被锁住,而旋转是自由的。
所以上面的例子创建的通用6自由度约束的意义是:将刚体“向上”平移5个单位后将平移锁死而允许自由旋转。
约束刚体的变换 在刚体的worldTransform之前作用与刚体,所以这里的“向上”是不对刚体进行worldTransform时的向上。
这就是为什么它等价于上述的btPoint2PointConstraint约束。
上面旋转是自由的,当然我们可以进行限制,比如只允许刚体绕某个轴进行旋转,下面的例子中我们分别限制只允许绕X轴、Y轴、Z轴旋转。
{ //允许绕X轴自由旋转,将Y轴、Z轴锁死
trans.setOrigin(btVector3(-10,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
spSlider6Dof = new btGeneric6DofConstraint(*d6body0,btTransform::getIdentity(),true);
spSlider6Dof->setAngularLowerLimit(btVector3(1.0, 0, 0));
spSlider6Dof->setAngularUpperLimit(btVector3(-1.0,0, 0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
{ //允许绕Y轴自由旋转,将X轴、Z轴锁死
trans.setOrigin(btVector3(0,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
spSlider6Dof = new btGeneric6DofConstraint(*d6body0,btTransform::getIdentity(),true);
spSlider6Dof->setAngularLowerLimit(btVector3(0, 1.0, 0));
spSlider6Dof->setAngularUpperLimit(btVector3(0, -1.0, 0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
{ //允许绕Z轴自由旋转,将X轴、Y轴锁死
trans.setOrigin(btVector3(10,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
spSlider6Dof = new btGeneric6DofConstraint(*d6body0,btTransform::getIdentity(),true);
spSlider6Dof->setAngularLowerLimit(btVector3(0, 0, 1.0));
spSlider6Dof->setAngularUpperLimit(btVector3(0, 0,-1.0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
trans.setOrigin(btVector3(-10,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
spSlider6Dof = new btGeneric6DofConstraint(*d6body0,btTransform::getIdentity(),true);
spSlider6Dof->setAngularLowerLimit(btVector3(1.0, 0, 0));
spSlider6Dof->setAngularUpperLimit(btVector3(-1.0,0, 0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
{ //允许绕Y轴自由旋转,将X轴、Z轴锁死
trans.setOrigin(btVector3(0,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
spSlider6Dof = new btGeneric6DofConstraint(*d6body0,btTransform::getIdentity(),true);
spSlider6Dof->setAngularLowerLimit(btVector3(0, 1.0, 0));
spSlider6Dof->setAngularUpperLimit(btVector3(0, -1.0, 0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
{ //允许绕Z轴自由旋转,将X轴、Y轴锁死
trans.setOrigin(btVector3(10,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
spSlider6Dof = new btGeneric6DofConstraint(*d6body0,btTransform::getIdentity(),true);
spSlider6Dof->setAngularLowerLimit(btVector3(0, 0, 1.0));
spSlider6Dof->setAngularUpperLimit(btVector3(0, 0,-1.0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
你可以下载附件中的代码替换ConstraintDemo中的同名文件来观看上面代码的效果 ConstraintDemo.rar
可以看到绕X轴自由旋转和绕Z轴自由旋转的约束都是正确的,而绕Y轴自由旋转的约束出现了异常。
从btGeneric6DofConstraint的注释中我们可以发现对转角的约束是有限制的
这个限制的存在应该和欧拉角的唯一性有关。(一个相似的例子是经纬度)
当定义超过限制的约束时,约束会变得十分诡异,另外,限制使得对Y轴的约束只能是locked或limited而不能是free
当我们想创建一个不会翻的车子,我们需要让Y轴自由旋转,而X轴和Z轴有一定限制,这时候怎么办?
一个解决办法如下:
{
trans.setOrigin(btVector3(0,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
btRigidBody* _bt_balancer_body = new btRigidBody(0,0,0);
m_dynamicsWorld->addRigidBody(_bt_balancer_body);
// must use X axis as Y axis because 6dof wont spin freely on Y
btTransform rotateZ( btTransform::getIdentity() );
rotateZ.getBasis().setEulerZYX( 0, 0, SIMD_HALF_PI );
spSlider6Dof = new btGeneric6DofConstraint(*d6body0, *_bt_balancer_body, rotateZ, rotateZ,true);
// 这里的约束条件是参照rotateZ表示的坐标系,是经过绕Z轴旋转的坐标系,这里的X轴是世界坐标系的Y轴,所以只需要设置旋转的X自由,而锁死Y,Z即可绕过对Y轴不能设置自由的限制。
spSlider6Dof->setAngularLowerLimit(btVector3(1.0, 0, 0));
spSlider6Dof->setAngularUpperLimit(btVector3(-1.0, 0, 0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
trans.setOrigin(btVector3(0,0,0));
d6body0 = localCreateRigidBody( mass,trans,shape);
d6body0->setActivationState(DISABLE_DEACTIVATION);
btRigidBody* _bt_balancer_body = new btRigidBody(0,0,0);
m_dynamicsWorld->addRigidBody(_bt_balancer_body);
// must use X axis as Y axis because 6dof wont spin freely on Y
btTransform rotateZ( btTransform::getIdentity() );
rotateZ.getBasis().setEulerZYX( 0, 0, SIMD_HALF_PI );
spSlider6Dof = new btGeneric6DofConstraint(*d6body0, *_bt_balancer_body, rotateZ, rotateZ,true);
// 这里的约束条件是参照rotateZ表示的坐标系,是经过绕Z轴旋转的坐标系,这里的X轴是世界坐标系的Y轴,所以只需要设置旋转的X自由,而锁死Y,Z即可绕过对Y轴不能设置自由的限制。
spSlider6Dof->setAngularLowerLimit(btVector3(1.0, 0, 0));
spSlider6Dof->setAngularUpperLimit(btVector3(-1.0, 0, 0));
m_dynamicsWorld->addConstraint(spSlider6Dof);
spSlider6Dof->setDbgDrawSize(btScalar(5.f));
}
效果如图:
附件为错误和正确限制示例的可执行文件 AppConstraintDemo_exe.rar
0 0
- Bullet Physics Engine(物理引擎)中使用约束
- 在Bullet Physics Engine中使用约束
- Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)
- Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)
- Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)
- Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)
- Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)
- Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide)
- Bullet physics物理引擎学习笔记
- AS3物理引擎 (AS3 Physics Engine)
- /LGC物理引擎/Havok physics engine 分析
- /LGC物理引擎/overview of Physics Engine
- AMD宣布将支持开源物理引擎Bullet Physics
- 开源物理引擎Bullet Physics下载与安装
- iOS 中引入Bullet 物理引擎
- bullet物理引擎btBvhTriangleMeshShape,btHeightfieldTerrainShape的使用
- Bullet物理引擎分析-约束分析之背景介绍
- Game.Physics.Engine.Development(游戏物理引擎开发)
- 第10、11周项目(2)-储存班长信息的学生类
- Matlab Tricks(七)—— 矩阵列/列的归一化/单位化(normalize)
- 下载Google地图,瓦片数据和经纬坐标的切换
- PhpStorm许可server地址
- Spring Boot 中使用log4jdbc记录SQL的运行时参数
- Bullet Physics Engine(物理引擎)中使用约束
- eclipse + pydev 创建django项目
- JSP简介
- spring通知-BeforeAdvice和AfterReturningAdvice
- split()方法字符串拆分
- 我生命中的钱事:创业!
- 菜鸟级别的Shiro配置、使用案例(一)
- stl set的用法
- SQL Server中常用的日期时间函数