<일러두기>

번역기 돌린것보다 조금 나은 수준이지만 의미전달에는 크게 무리가 없다고 생각합니다. 오역 지적, 좀더 나은 의견은 감사히 받습니다.

<원문보기>

About



<Contact>는 모양들 간의 충돌을 관리하기 위한 Box2D객체이다. 서로 다른 종류의 모양들 사이의 접촉을 관리하기 위해 b2Contact에서 파생된 서로 다른 종류의 몇 가지 컨택트가 존재한다. 예를들면 다각형-다각형 충돌을 관리하는 클래스와 원-원의 충돌을 관리하는 클래스가 있다. 이것들은 보통 당신에게는 중요하지 않지만, 적어도 당신이 알고 있을 필요는 있다.


다음에 몇가지 컨택트와 관련된 몇가지 용어가 있다. 이들은 Box2D 특유의 것이지만, 당신은 다른 물리엔진에서도 비슷한 용어들을 찾을 수 있을 것이다.


접점
접점은 두 모양이 접한 위치의 정점이다. 사실 객체들은 표면이 접했을 때 겹치게 되어 있다. Box2D는 적은 수의 접점으로 컨택트를 근사한다.
컨택트 법선
컨택트 법선은 접점을 기준으로 shape1에서 shape2로 향하는 단위 벡터이다.
컨택트 분리
분리는 관통의 반대이다, 분리는 모양들이 겹칠 때 음수가 된다. Box2D의 향후 버전에서는 양의 분리를 갖는 접점이 생성되도록 바뀔 수 있다. 따라서, 당신은 접점이 보고되었을 때 부호를 체크해야 할 지도 모른다.
법선 힘
Box2D는 상호작용적인 충돌처리기를 사용하고 충돌점을 결과와 함께 저장한다. 당신은 충돌 강도를 측정하는 데 안전하게 법선 힘을 사용할 수 있다. 예를 들면, 당신은 법선 힘을 부서지는 물체들에 대해 이벤트를 트리거하거나 충돌 사운드를 재생하는 데 사용할 수 있다.
탄젠트 힘
탄젠트 힘은 충돌 처리기의 마찰력에 대한 근사값이다.
충돌 ID
Box2D는 최초 타임스텝으로부터 추정된 충돌 결과를 다음 타임스텝에서도 재사용하려고 한다. Box2D는 타임스텝에 관계없이 충돌점을 확인하기 위해 충돌 ID를 사용한다. ID들은 한 충돌점을 다른 것들과 구별하게 해 주는, 기하학적 요소의 색인을 갖고 있다.

충돌들은 두 AABB(축정렬 경계상자)가 겹칠 때 생성된다. 때때로 충돌 필터는 컨택트의 생성을 막을 것이다. Box2D는 가끔, 충돌이 필터링되더라도 컨택트를 생성할 필요가 있다. 이 경우 컨택트의 발생을 막는 b2NullContact가 사용된다. 컨택트는 AABB들이 겹치지 않을 때 파괴된다.

So you might gather that there may be contacts created for shapes that are not touching (just their AABBs). Well, this is correct. It's a "chicken or egg" problem. We don't know if we need a contact object until one is created to analyze the collision. We could delete the contact right away if the shapes are not touching, or we can just wait until the AABBS stop overlapping. Box2D takes the latter approach.


Contact Listener

당신은 b2ContactListener를 구현함으로서 충돌 데이터를 얻을 수 있다. 이 리스너는 충돌점이 생성될 때, 그리고 1타임스텝 이상 지속될 때, 그리고 파괴될 때 보고한다.  두 모양이 복수의 충돌점을 가진다는것을 주지하라.

public class MyContactListener extends b2ContactListener
{
public override function Add(point:b2ContactPoint) : void
{
// handle add point
}
 
public override function Persist(point:b2ContactPoint) : void
{
// handle persist point
}
 
public override function Remove(point:b2ContactPoint) : void
{
// handle remove point
}
 
public override function Result(point:b2ContactResult) : void
{
// handle results
}
};

Caution

b2ContactListener에 들어오는 접점에 대한 참조를 만들지 말라. 대신 당신의 버퍼에 접점의 데이터를 깊은 복사로 넘겨라. 아래의 예제가 이를 위한 한가지 방법을 보여준다.
지속적인 물리는 단계적 진행을 사용한다. 그러므로 하나의 접점은 같은 타임스텝에서 추가되고 제거된다. 이는 일반적으로는 문제가 되지 않지만, 당신의 코드는 이를 우아하게 처리해야 한다.


접점은 추가되거나 지속하거나, 제거되는 즉시 보고된다. 이것은 처리자가 호출되기 전에 일어난다. 그러므로 b2ContactPoint 객체는 계산된 충격량을 갖지 않는다. 그러나 당신이 접촉시의 충격량을 어림할 수 있도록 접점에서의 상대속도가 제공된다. 만약 당신이 Result 함수를 구현했다면, 처리자가 호출된 이후의 실질적인 접점에 대한 b2ContactResult객체를 받을 것이다. 이들 결과 구조체는 하위 스텝의 충격량을 포함한다. 다시 말하면, 연속적인 물리를 위해 당신은 b2World.Step당 생성되는 복수의 점점 당, 복수의 결과를 받게 될 것이다.


이것은 컨택트 콜백 안에서 물리공간을 변화시키도록 게임 로직을 구현하도록 유혹한다. 예를 들면, 당신은 데미지를 를 적용하는 충돌을 보고받고 관련된 행동자와 그것의 강체를 파괴하려고 시도할 것이다. 그러나 Box2D는 당신이 콜백 안에서 물리공간을 변화시키도록 허용하지 않는다. 왜나하면 당신이 현재 Box2D가 처리하고 있는 물체를 파괴할 수 도 있고, 이것은 포인터를 고아로 만들기 때문이다.


접점 처리에 대한 추천할만한 관례는, 당신이 처리할 모든 접점을 버퍼에 넣고 해당 타임스텝이 끝난 다음에 처리하는 것이다. 당신은 항상 접점들을 타임스텝이 끝난 후에 곧바로 처리해야 한다. 그렇지 않으면 다른 클라이언트 코드가 물리공간을 변화시켜 놓을 것이고, 접점 버퍼가 쓸모없어지기 때문이다. 당신이 접점 버퍼를 처리할 때는 물리 공간을 변화시킬 수 있지만, 접점 버퍼에 고아가 된 포인터를 넣지 않도록 당신은 여전히 주의해야 한다.

아래의 코드는 충돌 처리 테스트(test_CollisionProcessing.py)를 포팅한 것 중에서 발췌한 것이며, 어떻게 접점 버퍼를 처리하는 중에 고아가 된 강체를 어떻게 처리하는지 보여준다.


// 우리는 접점에 관련된 몇 강체를 파괴할 것이다.
// 우리는 파괴되어야 하는 강체들을 버퍼에 넣어야 한다.
// 왜냐하면 그것들은 복수의 접점에 속해있을 것이므로.
var k_maxNuke:int = 6
var nuke:Array = new Array();
var nukeCount:int = 0

 
// 충돌 결과를 통과시킨다.
// 보다 더 무거운 강체에 닿은 강체를 파괴한다.
for each(var point:ContactPoint in contactPoints)
{

var body1:b2Body = point.body1.GetBody();
var body2:b2Body = point.body2.GetBody();
var mass1:Number = body1.GetMass();
var mass2:Number = body2.GetMass();
 
if(mass1 > 0.0 and mass2 > 0.0){
if(mass2 > mass1){
nuke_body = body1;
} else {
nuke_body = body2;
}
if (nuke.indexOf(nuke_body) == -1){
nuke.push(nuke_body);
if(nuke.length == k_maxNuke)
break;
}
}
}


// 강체를 파괴한다. 중복된 것은 넘어간다.
for each(var b:b2Body in nuke){
trace("Nuking:", b);
self.world.DestroyBody(b);
}


Contact Filtering

당신은 종종 게임 안의 모든 물체가 충돌을 일으키는 것을 바라지 않을 것이다. 예를 들면 당신은 정해진 캐릭터만 통과할 수 있는 문을 만들고 싶을 수도 있다. 이것을 컨택트 필터링이라 부른다. 일부 상호작용이 걸러지기 때문이다.


Box2D는 당신이 b2ContactFilter 클래스를 구현함으로서 커스텀 필터를 얻는 것을 허용한다. 이 클래스는 당신이 두 개의 b2Shape포인터를 받는 ShouldCollide 함수를 구현할 것을 요구한다. 당신이 구현할 함수는 두 모양이 충돌한다면 참을 반환하는 것이다.


ShouldCollide의 기본적인 구현은, 모양 챕터의 필터링 섹션에 구현된 b2FilterData를 사용한다.


public class b2ContactFilter
{
 
/// Return true if contact calculations should be performed between these two shapes.
/// @warning for performance reasons this is only called when the AABBs begin to overlap.
public virtual function ShouldCollide(shape1:b2Shape, shape2:b2Shape) : Boolean{
var filter1:b2FilterData = shape1.GetFilterData();
var filter2:b2FilterData = shape2.GetFilterData();
 
if (filter1.groupIndex == filter2.groupIndex && filter1.groupIndex != 0)
{
return filter1.groupIndex > 0;
}
 
var collide:Boolean = (filter1.maskBits & filter2.categoryBits) != 0 && (filter1.categoryBits & filter2.maskBits) != 0;
return collide;
}
 
static public var b2_defaultFilter:b2ContactFilter = new b2ContactFilter();
 
};
저작자 표시 비영리 동일 조건 변경 허락