두 개의 움직이는 AABB가 교차하는지 확인하는 가장 빠른 방법은 무엇입니까?


12

움직이는 AABB가 두 개 있는데, 프레임 아래에서 교차하는지 확인하는 가장 빠른 방법은 무엇입니까?

이동하면 일반적인 사각형 교차 방법으로 확인하는 것이 아니라 부울, 적중 시간 또는 다른 것을 반환하지 않는 간단한 쉬운 스윕 테스트를 의미합니다.

내가 생각하는 것은 단순히 다음과 같이하는 것입니다.

이

그러나 육각형은 매우 복잡하며 AABB-다각형 교차점을 계산하는 방법을 모르겠습니다. 더 쉬운 방법이 있습니까?

가장 좋아하는 프로그래밍 언어는 쉽게 이식 할 수 있습니다.

감사.


3
혼란 스러워요. "스윕 테스트"에 대해 구체적으로 언급하고 일반적인 AABB 스윕 테스트를 시도 했습니까? 정확히 원하는 것을 수행합니다.
SomeWritesReserved

1
위의 의견에 동의합니다. "클래식"테스트의 문제점은 무엇입니까? 또한 여기에 제안 된 솔루션의 대부분은 그보다 명확하게 느립니다 ... 또한 일부 솔루션은 잘못된 결과를 제공 할 수 있습니다 (강력하지는 않음).
wondra

당신은 Separating Axis Test gamedevelopment.tutsplus.com/tutorials/…를
Pharap

답변:


8

Minkowski 합계 사용

이 문제를 해결하는 좋은 방법은 운동의 라인 사이의 교차점을 고려하는 것입니다 ( V ) 원점 (번역 V ' )과 민코프 스키 합A는 원점 (180도 회전 A' )와 장애물 (단지 B 이 경우) A 'B .

다음 그림 I 장소에서 헤로인-DAB 임의의 원점 좌표계. 이렇게하면 A를 180 도로 회전 시키면 A ' 가되고 v 가 원점으로 변환 된 v는 v' 와 같이 이해가 간단 해 집니다.

Minkowski 합은 녹색 사각형이며, AAAA 선을 교차 하여 움직이는 A 와 고정 B의 교점을 찾을 수 있습니다 . 이 점들은 파란색 원으로 표시됩니다.

민코프 스키 합계-퇴보 사례

다음 그림에서는 다른 원점이 사용되었으며 동일한 교차점이 발견되었습니다.

Minkowski 합계-보다 일반적인 경우

여러 개의 움직이는 AABB

특정 기간 동안 선형 방식으로 움직이는 두 AABB에 대해이 작업을 수행하려면 A 의 속도 벡터에서 B 의 속도 벡터를 빼고이를 AAAA 교차점의 선분으로 사용합니다.

의사 코드

def normalize(aabb):
    return {x1: min(aabb.x1, aabb.x2), x2: max(aabb.x1, aabb.x2),
            y1: min(aabb.y1, aabb.y2), y2: max(aabb.y1, aabb.y2),

def rotate_about_origin(aabb):
    return normalize({x1: -aabb.x1, x2: -aabb.x2
                      y1: -aabb.y1, y2: -aabb.y2})

# given normalized aabb's
def minkowski_sum(aabb1, aabb2):
    return {x1: aabb1.x1+aabb2.x1, x2: aabb1.x2+aabb2.x2,
            y1: aabb1.y1+aabb2.y1, y2: aabb1.y2+aabb2.y2}

def get_line_segment_from_origin(v):
    return {x1: 0, y1: 0, x2: v.x, y2: v.y}

def moving_objects_with_aabb_intersection(object1, object2):
    A = object1.get_aabb()
    B = object2.get_aabb()

    # get A'⊕B
    rotated_A = rotate_about_origin(A)
    sum_aabb = minkowski_sum(rotated_A, B)

    # get v'
    total_relative_velocity = vector_subtract(object1.get_relative_velocity(), object2.get_relative_velocity())
    line_segment = get_line_segment_from_origin(total_relative_velocity)

    # call your favorite line clipping algorithm
    return line_aabb_intersection(line_segment, sum_aabb)

충돌 대응

게임 플레이에 따라 더 세밀한 충돌 감지 (AABB에는 메시가 포함되어 있음)를 수행하거나 다음 단계 인 충돌 응답으로 넘어갑니다.

충돌이 발생하면 AABB 교차로 알고리즘은 A가 B 내부의 움직임을 종료하는지 또는 통과하는지에 따라 1 또는 2 개의 교차점을 반환합니다. (이것은 A가 측면을 따라 또는 각각의 모서리 중 하나를 따라 B를 움켜 쥐는 퇴화 된 경우를 할인합니다.)

어느 쪽이든, 선분을 따르는 첫 번째 교차점은 충돌 점입니다.이를 다시 월드 좌표계의 정확한 위치로 변환합니다 (원래 v를 따라 두 번째 그림의 첫 번째 밝은 파란색 원은 p 라고 부릅니다) 그런 다음 프레임 끝에서 A 의 실제 위치 가 ( At + 1 )이 되는지 를 결정합니다 (예 : p 에서 충돌 법선을 따라 v 를 반사하여 탄성 충돌 의 경우 ).

충돌 대응

콜 리더가 두 개 이상인 경우 v 의 두 번째 반사 부분에 대한 충돌 감지를 원할 때 조금 더 복잡해 집니다.


고마워, 가장 흥미로운. 이동 중에 A와 B가 교차하는 경우를 처리하는 방법을 설명해 주시겠습니까?
GameAlchemist

@GameAlchemist 충돌 반응이 많고, 충돌 탐지 (질문의 원래 주제)는 그리 많지 않습니다. 그러나 그림판을 좋아하므로 편집 내용을 확인하십시오. :-)
Eric

업데이트 (및 계획 :-)에 감사드립니다), 이것은 내 질문이 아니지만 A가 B를 완전히 통과했을 때 알고리즘이 이미 사건을 처리한다는 것을 이해하는 데 도움이되었습니다.
GameAlchemist

5

OBB-방향 바운딩 박스. 튜토리얼은 다음과 같습니다

효과적으로, 경계 상자는 y 축 (위)으로서 객체 A의 속도 벡터와 정렬됩니다. 너비와 높이는 개체 A의 시작 및 끝 지점으로 계산할 수 있습니다. 그런 다음이를 개체 B의 AABB (OOBB로 처리) 및 황금과 비교합니다.

교차 할 수 있는지 확인하기 위해 빠른 교차 테스트를 원한다면 시작 위치와 끝 위치에서 객체 A의 AABB를 둘러싸는 AABB를 만들 수 있습니다. AABB가 AABB를 포괄하는이 모두와 교차하지 않으면 교차점이 없습니다. 그러나 이는 오 탐지로 이어질 수 있으므로 예비 테스트로만 사용해야합니다.


4

OOB가 필요하지 않으며 타임 스텝핑 충돌 탐지를 사용할 필요가 없습니다. 일반적인 AABB 스윕 테스트를 사용하십시오 ( 이 링크 참조) . 본질적으로 다이어그램에있는 것과 정확히 일치합니다. 이동하는 AABB는 시작 지점에서 "끝으로"스윕 된 다음 다른 정적 AABB에 대한 충돌 감지에 사용됩니다.

이 스위프 테스트가 "충격 시간"을 반환하기 때문에 더 비싸다고 걱정되는 경우, 조기 최적화하는 것 같습니다.

스윕 된 테스트에 대한 자세한 정보는 Christer Ericson의 " 실시간 충돌 감지 "라는 훌륭한 책에서 찾을 수 있습니다 .


3

AABB 근사 엣지 약점

먼저 이동을 작은 단계로 분해하고 해당 정보를 사용하여 높은 수준의 AABB를 계산해야합니다. 큰 AABB가 교차하는 경우 더 작은 단계를 더 정확하게 확인할 수 있습니다.

시작 및 끝 위치 만 사용하여 AABB (또는 OOBB)를 검사하여 충돌이 있었는지 여부를 추정하면 어느 한 객체가 빠르게 회전하고 한 차원에서 다른 차원보다 긴 경우 충돌을 놓칠 수 있습니다.

보다 정확한 추정 AABB를 계산하려면 움직임을 더 작은 단계로 분해하고 초기 AABB (오브젝트 메시 아님) 만 사용하여 오브젝트가 회전하고 각각 이동할 때 AABB (현재는 축이 정렬되지 않은 상자 만)를 회전하십시오. 단계. 각 축의 최대 및 최소 포인트는 객체의 전체 움직임을 둘러싸는 AABB를 제공합니다.

더 큰 AABB와 교집합이 있다면, 이미 계산 된 더 작은 AABB를 사용하여 충돌이 발생한 위치를 결정할 수 있습니다. 다른 물체와 교차하는 더 작은 AABB 각각에 대해 더 비싼 메시 교차 감지를 수행 할 수 있습니다.


2
또는 BB가 모든 회전에 대해 할 수있는 최대 너비를 미리 계산하여 사용하십시오.
ratchet freak

2

움직임을 더 작은 단계로 분해해야합니다. 예를 들면 다음과 같습니다.

큰 구성 요소 (이 경우 X 축)를 사용하여 이동을 분해 한 다음 각 단계에서 충돌을 확인하려고합니다.

이것은 너무 비싸 보일 수 있지만, 매 사이클마다 자신의 너비보다 빠르게 움직이는 객체는 EXTREMELLY가 빠르다는 점을 고려하십시오. 따라서이 시나리오는 처음 생각하는 것만 큼 흔하지 않습니다.


2
이 방법은 일부 사례 (예 : 상자가 첫 번째와 두 번째에 가까운 상자)에 걸리지 않으며 샘플링을 늘리는 것은 너무 과도합니다. SAT를 사용한 간단한 다각형 테스트는 빠르고 안정적이어야합니다.
Sopel

1
예, 이것은 괜찮은 해결책이지만 너무 크지는 않습니다. 충돌이 물체의 모서리에 가까워지면 정확도가 급격히 떨어지고 속도가 증가함에 따라 (또는 구현에 따라 정확도가 떨어짐) 성능이 떨어지며 불필요하게 해킹됩니다.
BWG

2

또한 AABB가 "정적"이고 다른 하나가 자체 속도로 "정적"속도를 뺀 속도로 충돌 확인을 위해 상대 속도를 사용해야합니다.

교차 할 있는지 확인하는 가장 빠른 방법 은 이동 AABB를 속도로 확장하는 것입니다.

예를 들어 AABB가 0.1 x / 프레임으로 오른쪽으로 이동 한 다음 왼쪽 가장자리가 동일하게 유지되고 오른쪽 가장자리가 0.1이되도록 확장합니다. 그런 다음 새로운 AABB로 확인할 수 있습니다. 거짓이면 충돌이 없습니다. (작은 속도에 대해서는 초기 귀환 및 정확).

그런 다음 움직이는 물체의 끝과 시작 AABB가 교차하는지 확인할 수 있습니다. true이면 true를 리턴하십시오.

그렇지 않으면 대각선이 정적 ABB와 교차하는지 확인해야합니다.

여기에는 대각선의 좌표를 얻는 것이 포함됩니다. 여기서 x는 정적의 왼쪽 가장자리이고 오른쪽 가장자리는 y가 아래쪽과 위쪽에 있는지 확인합니다. (다른 방법으로 반복)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.