对于旋转关节场常见的包括如下:
创建旋转关节
创建旋转关节首先设置b2RevoluteJointDef属性,然后用世界对象创建之.
然后我们看一堆关于旋转关节的属性。
下面就用图形化来详细解释这些属性对旋转关节(RevoluteJoint)的作用.
1.localAnchorA 和 localAnchorB.
这两个属性实际都是坐标点.而这两个坐标点都是基于刚体A和刚体B的自身本地坐标系而言的.比如:刚体A是一个宽度和高度都是4的正方形.若localAnchorA是b2Vec2(2,2).则localAnchorA这个点就在刚体A的最右上角.因为刚体A的原点(origin point)是在刚体A的正中心(刚体A的锚点默认是(0.5,0.5)),所以b2Vec2(2,2)就自然是在正方形的最右上角.
见下图:
见上图:假设正方形的宽高是2,原点是在正中心.则localAnchorA(1,1)就在其右上角. localAnchorB(0,0)就是圆的正中心.这样就相当于把正方形的右上角和圆的中心重合,并用一个旋转关节(RevoluteJoint)进行固定.就像一颗钉子一样.
2.eferenceAngle 参考角度.
参考角度实际上就是刚体B减去刚体A的角度.如果这个值为0,就是表示两个刚体的角度差为0,参考角度实际上就是关节的角度,在程序中可以通过GetJointAngle()来查看关节的旋转程度。当你使用关节限制(joint limits)的时候,参考角度还是有用的。
看下图:
在上图中的左边图,如果参考角度为0, 则在B逆时针旋转45角后(右边图),通过GetJointAngle()返回关节角度的值为45.即在参考角度上加45.
在上图中的左边图,如果参考角度为123,则在B逆时针旋转45角后(右边图),通过GetJointAngle()返回关节角度的值为168.即在参考角度上加45.
注意一下,bodyB的旋转可以作为关节的角度值,并且相对于bodyA是逆时针方向。如果两个物体同时被移动或旋转,关节角度是不会改变的,因为它代表的是两个物体的相对角度(Angle_B - Angle_A)。
3.旋转关节限制(revolute joint limits)
根据目前为止我们所讲解的属性来看,关节中的两个物体可以无限制的围绕锚点旋转,但是旋转关节也可以对旋转范围作出限制。可以对旋转的上限和下限作出设定,可以在’关节角度(joint angle)’方面作出设定。
假设你想对上面的例子在初始设定角度的时候范围限定在45度内
当使用关节限制的时候有些东西需要牢记…
bool atLowerLimit = joint->GetJointAngle() <= joint->GetLowerLimit(); bool atUpperLimit = joint->GetJointAngle() >= joint->GetUpperLimit();
一个关节限制强制关节角度保持在lower和upper之间。限制范围应该包含0,否则关节将在模拟开始的时候发生倾斜.
4.旋转连接器马达revolute joint motor
旋转关节默认的行为是没有阻力的。如果你想控制物体运动让其旋转,需要对其施加力矩或转动惯量。也可以设置能够让关节以某个特定的线速度旋转物体的关节’马达’。如果你想模拟具有动力效果的事物,比如汽车轮子或吊桥类型的门,这个特性还是很有用的。
线速度仅仅是一个目标速度,这也就意味着关节并不能保证达到这个速度。通过为关节马达指定最大可允许的扭矩,你能够控制关节最终达到目标速度的快慢程度,甚至在有些例子中决定了最终是否能够达到目标速度.下面一段引文解释了joint motor的最大扭矩.英文很简单我就不翻译了。
A joint motor allows you to specify the joint speed (the time derivative of the angle). The speed can be
negative or positive. A motor can have infinite force, but this is usually not desirable. Recall the eternal
question:
"What happens when an irresistible force meets an immovable object?"
I can tell you it's not pretty. So you can provide a maximum torque for the joint motor. The joint motor
will maintain the specified speed unless the required torque exceeds the specified maximum. When the
maximum torque is exceeded, the joint will slow down and can even reverse.
使用关节马达的时候需要注意一些事情…
下面以一个实例来进行说明.
首先是初始化:
//设置重力 b2Vec2 gravity; gravity.Set(0.0f, 0.0f); m_world = new b2World(gravity); //设置是否sleep m_world->SetAllowSleeping(true); m_world->SetContinuousPhysics(true); //创建GLESDebugDraw对象.在DEBUG调试环境下对刚体轮廓和关节等信息 //进行绘制。它是在b2World::Step中被调用. m_DebugDraw = new GLESDebugDraw(32.0f); m_world->SetDebugDraw(m_DebugDraw); uint32 flags = 0; //e_shapeBit:刚体的轮廓被绘制出来 flags += b2Draw::e_shapeBit; m_DebugDraw->SetFlags(flags);
然后创建正方形和圆形的刚体
b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; b2FixtureDef fixtureDef; fixtureDef.density = 1; fixtureDef.filter.groupIndex = int16(1); fixtureDef.filter.categoryBits = uint16(2); fixtureDef.filter.maskBits = uint16(12); b2PolygonShape boxShape; boxShape.SetAsBox(2,2); CCSize size = CCDirector::sharedDirector()->getWinSize(); bodyDef.position.Set(size.width/2/32, size.height/2/32); fixtureDef.shape = &boxShape; m_bodyA = m_world->CreateBody( &bodyDef ); m_bodyA->CreateFixture( &fixtureDef ); b2BodyDef bodyDefEx; bodyDefEx.type = b2_dynamicBody; bodyDefEx.position.Set(size.width/2/32, size.height/2/32); b2FixtureDef fixtureDedEx; fixtureDedEx.density = 1; fixtureDedEx.filter.groupIndex = int16(1); fixtureDedEx.filter.categoryBits = uint16(4); fixtureDedEx.filter.maskBits = uint16(12); b2CircleShape boxShapeEx; boxShapeEx.m_radius = 2; fixtureDedEx.shape = &boxShapeEx; m_bodyB = m_world->CreateBody(&bodyDefEx); m_bodyB->CreateFixture(&fixtureDedEx);
最后创建关节,把两个刚体连接起来.
b2RevoluteJointDef revoluteJointDef; revoluteJointDef.bodyA = m_bodyA; revoluteJointDef.bodyB = m_bodyB; revoluteJointDef.collideConnected = false; revoluteJointDef.localAnchorA.Set(2,2); revoluteJointDef.localAnchorB.Set(0,0); revoluteJointDef.motorSpeed = 100; revoluteJointDef.maxMotorTorque = 100; revoluteJointDef.enableMotor = true; revoluteJointDef.referenceAngle = 0; revoluteJointDef.enableLimit = true; revoluteJointDef.lowerAngle =-45 ; revoluteJointDef.upperAngle = 45; m_joint = (b2RevoluteJoint*)m_world->CreateJoint( &revoluteJointDef );
刚体A顺时针旋转。刚体B逆时针旋转.
没看到哪里可以上传附件的地方。郁闷。否则把源代码传上去 。