이것은
바퀴, 롤러, 사슬, 선개교, 봉제 인형, 회전문, 투석기, 레버
등에 이용된다.
localAnchorA - 강체 A가 그 주변에서 회전할 정점
localAnchorB - 강체 B가 그 주변에서 회전할 정점
referenceAngle - 처음의 강체간 각도를 0으로(변경 가능) 하는 접합점의 회전각
enableLimit - 접합점의 회전제한 여부
lowerAngle - 하한각
upperAngle - 상한각
enableMotor - 접합점의 모터의 활성화 여부
motorSpeed - 모터의 목적 속도
maxMotorTorque - 모터가 사용가능한 최대 토크의 크기
을 속성으로 가진다.
- 지역 거점
revoluteJointDef.localAnchorA.Set(1,1);
revoluteJointDef.localAnchorB.Set(0,0);
사각형이 A, 원이 B
이 값은 GetAnchorA() 와 GetAnchorB() 메서드를 통해 얻을 수 있다.
주의할 것은 고정체를 연결하는 것이 아닌 강체를 연결한다는 것이다.
항상 Box2D에서 위 두 강체를 접합시킬 수 있는 것은 아니며, 지속적으로 우측의 그림과 같이 형상을 유지하도록 힘을 가한다.
- 참조 각
revoluteJointDef.referenceAngle = 0; //기본값이기도 하다.
이 각은 GetJointAngle() 메서드를 통해 가능한데 얻는 값은 referenceAngle의 초기 설정값에 따라 그림의 우측과 같이 다르게 출력된다.
이 각은 강체간 사이의 각도에 관계되어 있으므로 위와 같이 저 전체가 회전하였다고 하여도 GetJointAngle() 메서드의 출력값은 변하지 않는다.
- 회전각 제한
revoluteJointDef.enableLimit = true;
revoluteJointDef.lowerAngle = -45 * DEGTORAD;
revoluteJointDef.upperAngle = 45 * DEGTORAD;
제한을 걸게 되면, 상한, 하한 모두 같이 제한이 설정된다. 즉, 하나만 제한을 걸 수 없다. 따라서 상한만 제한을 걸고자 한다면, 하한의 제한값을 크게 낮게 잡아야 한다.
void EnableLimit(bool enabled);
void SetLimits( float lower, float upper );
bool IsLimitEnabled();
float GetLowerLimit();
float GetUpperLimit();
이 메서드로 실행 중 값을 얻어올 수 있다.
물론 이 또한 큰 속도로 강체가 회전하고 있었을 경우, 제한을 넘겼을 때, 잠깐 초과된 모습이 화면에 그려질 수 있으나 곧 Box2D가 제한점으로 위치시킨다.
현재 접합점이 제한점 상에 있는지를 확인하는 방법은 간단하며 다음과 같다.
bool atLowerLimit = joint->GetJointAngle() <= joint->GetLowerLimit();
bool atUpperLimit = joint->GetJointAngle() >= joint->GetUpperLimit();
- 모터
기본 접합점의 행동방식은 저항 없이 회전하는 것이다. 허나 모터를 적용하여 이를 회전시킬 수 있다. 회전은 각속도를 명시함으로 이루어진다. 단 이는 최대 도달가능한 각속도를 명시하는 것이며 즉시 속도를 설정하는 것이 아니다.
회전을 시키는 것은 토크의 크기를 지정함으로써 이루어진다. 이 말은 반드시 최대 각속도에 도달할 수 있다는 보장이 없다는 것이다.
revoluteJointDef.enableMotor = true;
revoluteJointDef.maxMotorTorque = 20;
revoluteJointDef.motorSpeed = 360 * DEGTORAD;
//alter joint motor
void EnableMotor(bool enabled);
void SetMotorSpeed(float speed);
void SetMaxMotorTorque(float torque);
//query joint motor
bool IsMotorEnabled();
float GetMotorSpeed();
float GetMotorTorque();
최대 각속도를 0으로 지정할 경우 모터는 브레이크와 같은 역할을 하게 된다.
Testbed에는 0, 0에 정적 강체가 멤버로 존재한다. 그 이름은 m_goundBody 이다.
다음은 맨 상위 주소에서 제공한 튜토리얼의 결과이다.
접합점을 연결한 강체 두개와, 체인을 하나 생성해 본다.
#ifndef __MYREVOLUTEJOINTTEST_H__
#define __MYREVOLUTEJOINTTEST_H__
class MyRevoluteJointTest : public Test {
public:
//각각 강체와 접합점의 포인터.
b2Body* m_bodyA, *m_bodyB;
b2RevoluteJoint* m_joint;
MyRevoluteJointTest(){
//이하는 맵을 정의
//body definition
b2BodyDef myBodyDef;
myBodyDef.type = b2_dynamicBody;
//shape definition
b2PolygonShape polygonShape;
polygonShape.SetAsBox(1, 1); //a 2x2 rectangle
//fixture definition
b2FixtureDef myFixtureDef;
myFixtureDef.shape = &polygonShape;
myFixtureDef.density = 1;
//create dynamic body
myBodyDef.position.Set(0, 10);
//pBody1 = m_world->CreateBody(&myBodyDef);
//pBody1->CreateFixture(&myFixtureDef);
//a static body
myBodyDef.type = b2_staticBody;
myBodyDef.position.Set(0, 0);
b2Body* staticBody = m_world->CreateBody(&myBodyDef);
//add four walls to the static body
polygonShape.SetAsBox( 20, 1, b2Vec2(0, 0), 0);//ground
staticBody->CreateFixture(&myFixtureDef);
polygonShape.SetAsBox( 20, 1, b2Vec2(0, 40), 0);//ceiling
staticBody->CreateFixture(&myFixtureDef);
polygonShape.SetAsBox( 1, 20, b2Vec2(-20, 20), 0);//left wall
staticBody->CreateFixture(&myFixtureDef);
polygonShape.SetAsBox( 1, 20, b2Vec2(20, 20), 0);//right wall
staticBody->CreateFixture(&myFixtureDef);
//이하는 두 강체를 연결하는 단계,
//body and fixture defs - the common parts
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
b2FixtureDef fixtureDef;
fixtureDef.density = 1;
//two shapes
b2PolygonShape boxShape;
boxShape.SetAsBox(2,2);
b2CircleShape circleShape;
circleShape.m_radius = 2;
//make box a little to the left
bodyDef.position.Set(-3, 10);
fixtureDef.shape = &boxShape;
m_bodyA = m_world->CreateBody( &bodyDef );
m_bodyA->CreateFixture( &fixtureDef );
//and circle a little to the right
bodyDef.position.Set( 3, 10);
fixtureDef.shape = &circleShape;
fixtureDef.friction = 0.5;
m_bodyB = m_world->CreateBody( &bodyDef );
m_bodyB->CreateFixture( &fixtureDef );
b2RevoluteJointDef revoluteJointDef;
revoluteJointDef.bodyA = m_bodyA;
revoluteJointDef.bodyB = m_bodyB;
revoluteJointDef.collideConnected = false;
revoluteJointDef.localAnchorA.Set(2,2);//the top right corner of the box
revoluteJointDef.localAnchorB.Set(0,0);//center of the circle
//revoluteJointDef.localAnchorA.Set(4,4);//the top right corner of the box
//revoluteJointDef.localAnchorB.Set(-2,0);//center of the circle
//revoluteJointDef.enableLimit = true;
//revoluteJointDef.lowerAngle = -45 * DEGTORAD;
//revoluteJointDef.upperAngle = 45 * DEGTORAD;
revoluteJointDef.enableMotor = true;
revoluteJointDef.maxMotorTorque = 225;
revoluteJointDef.motorSpeed = 1390 * DEGTORAD;//90 degrees per second
m_joint = (b2RevoluteJoint*)m_world->CreateJoint( &revoluteJointDef );
{//이하는 체인 생성을 위한 단계
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(5,10);
b2FixtureDef fixtureDef;
fixtureDef.density = 1;
b2PolygonShape polygonShape;
polygonShape.SetAsBox(1,0.25);
fixtureDef.shape = &polygonShape;
//create first link
b2Body* link = m_world->CreateBody( &bodyDef );
link->CreateFixture( &fixtureDef );
//set up the common properties of the joint before entering the loop
b2RevoluteJointDef revoluteJointDef;
revoluteJointDef.localAnchorA.Set( 0.75,0);
revoluteJointDef.localAnchorB.Set(-0.75,0);
//use same definitions to create multiple bodies
for (int i = 0; i < 10; i++) {
b2Body* newLink = m_world->CreateBody( &bodyDef );
newLink->CreateFixture( &fixtureDef );
//...joint creation will go here...
//inside the loop, only need to change the bodies to be joined
revoluteJointDef.bodyA = link;
revoluteJointDef.bodyB = newLink;
m_world->CreateJoint( &revoluteJointDef );
link = newLink;//prepare for next iteration
}
//body with circle fixture
b2CircleShape circleShape;
circleShape.m_radius = 2;
fixtureDef.shape = &circleShape;
b2Body* chainBase = m_world->CreateBody( &bodyDef );
chainBase->CreateFixture( &fixtureDef );
//a revolute joint to connect the circle to the ground
revoluteJointDef.bodyA = m_groundBody;//provided by testbed
revoluteJointDef.bodyB = chainBase;
revoluteJointDef.localAnchorA.Set(4,20);//world coords, because m_groundBody is at (0,0)
revoluteJointDef.localAnchorB.Set(0,0);//center of circle
m_world->CreateJoint( &revoluteJointDef );
//another revolute joint to connect the chain to the circle
revoluteJointDef.bodyA = link;//the last added link of the chain
revoluteJointDef.bodyB = chainBase;
revoluteJointDef.localAnchorA.Set(0.75,0);//the regular position for chain link joints, as above
revoluteJointDef.localAnchorB.Set(1.75,0);//a little in from the edge of the circle
m_world->CreateJoint( &revoluteJointDef );
}
}
void Step(Settings* settings){
Test::Step(settings);
}
void MouseDown(const b2Vec2& p){
b2Vec2 pp = p;
pp.y = pp.y -1;
Test::MouseDown(pp);
}
static Test* Create(){
return new MyRevoluteJointTest();
}
};
#endif
이상. 기록 끝.
댓글 없음:
댓글 쓰기