작은 고속 객체 충돌 : 터널링 방지


14

편집 / 업데이트 : 지금 가장 큰 질문은 3 단계의 "t = ..."방정식이 좋은 아이디어인지 또는 더 좋은 방법인지 여부입니다. 대부분의 다른 문제는 부분적으로 또는 전체적으로 해결되었지만 실제로이 문제에 대한 의견이나 답변은 없습니다. 다시 말하지만, 분석 솔루션이 필요할 수도 있고, 속도와 거리가 너무 길고, 객체가 너무 작습니다. 이런 종류의 상황을 잘 처리 할 수있는 특수 반복 / 재귀 솔루션은 분명히 열려 있습니다.) 지금까지 도와 주셔서 감사합니다. 모두 훌륭하고 여러분의 생각과 도움에 정말 감사드립니다!

작은 고속 물체 사이의 충돌을 감지하려고합니다. 이것은 상대적으로 낮은 속도에서도 터널링이 매우 쉽게 발생할 수있는 상황입니다.

광선 주조는 작동하지 않습니다. 하나의 물체와 고정 벽 사이가 아니라 두 개의 고속 물체 사이의 충돌을 감지하기 때문입니다. (레이 캐스팅을 오해하지 않는 한?) 성능은 매우 중요합니다. 가능하다면 큰 성능 저하를 피하고 싶습니다. 이미 기능적이고 매우 효과적인 쿼드 트리 ( http://en.wikipedia.org/wiki/Quadtree )가 구현되어 있으므로 아래에 설명 된대로 수정하고 사용해야합니다.

편집 : 시간 간격을 줄이면 작동하지 않습니다. 이 솔루션의 속도가 너무 빠르기 때문에 성능 충돌이 너무 커져도 터널링 충돌의 대부분은 여전히 ​​사라 집니다. (예를 들어, 시간 간격 당 수백만 단위로 측정 된 속도로 진행하는 크기가 약 1 단위 인 물체가있을 수 있습니다 ...)

제안 된 해결책:

1 단계:

각 객체의 움직임 주위에 상자를 만든 다음 해당 상자를 쿼드 트리에 공급하여 가능한 충돌의 초기 목록을 생성합니다. 다음 이미지를 참조하십시오 (이 이미지는 한 위치에서 다른 위치로 이동하는 원 오브젝트와 사각형을 생성하는 움직임을 보여 주며, 이는 쿼드 트리에 공급됩니다)움직임에 의해 생성 된 사각형

2 단계 : (이 단계를 건너 뛰고 싶습니까?)

쿼드 트리에서 생성 된 가능한 충돌 목록을 살펴 봅니다. 가능한 각 충돌에서 사각형이 교차하는지 확인하십시오. 그렇다면 3 단계로 진행하십시오.

편집 : 아래에서 Sean Middleditch는 스윕 볼륨 / 캡슐의 교차점 (객체가 원인 경우)을 사용하도록 제안했습니다. 1) 2 단계를 완전히 건너 뜁니다. 2) 2 단계를 수행하십시오. 3) Sean의 방식으로하십시오. Sean의 방법은 내 상자 아이디어보다 계산 비용이 많이 들지만 내 방법보다 더 많은 오 탐지를 제거하여 최종 단계에 도달하지 못하게합니다.

누구든지이 세 가지 선택 중에서 가장 좋은 것에 대해 경험을 통해 말할 수 있습니까? (이 물리 엔진을 몇 가지 다른 용도로 사용하려고하므로 어떤 솔루션을 쉽게 측정 할 수있는 하나의 특정 테스트 사례가 아니라 가장 광범위한 상황에서 가장 빠르게 작동하는 "일반적으로 최상의"솔루션을 찾고 있습니다. 가장 빠릅니다).

3 단계 :

판별 (즉, 제곱근 아래 부분)이 음수이거나 0이면 충돌이 없으면 아래의 t = 방정식을 사용하고, 양수이면 충돌 시간으로 t 값을 사용하십시오 (그 후에 위치를 쉽게 조정할 수 있음). 충돌 후 두 개체가 모두 계속 존재하는 경우). 방정식:

t = (-1/2 sqrt ((2 a w-2 a x + 2 b y-2 b z-2 c w + 2 c x-2 d y + 2 dz)) ^ 2-4 (w ^ 2- 2w x + x ^ 2 + y ^ 2-2 y z + z ^ 2) (a ^ 2-2 a c + b ^ 2-2 b d + c ^ 2 + d ^ 2-r ^ 2-2 r ss ^ 2))-a w + a xb y + b z + c wc x + d yd z) / (w ^ 2-2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2 ) .

여기서 (1과 2는 객체 1과 2를 나타내는 데 사용됩니다) :

t는 0과 -1 사이의 음의 시간 값이며, 여기서 0은 현재 프레임이고 -1은 이전 프레임입니다.

a = x 위치 1;

b = y 위치 1;

c = x 위치 2;

d = y 위치 2;

w = x 속도 1;

x = x 속도 2;

y = y 속도 1;

z = y 속도 2;

r = 반경 1;

s = 반경 2;

유도 : (^ 2는 제곱을 의미합니다)

객체의 움직임에 대한 파라 메트릭 방정식 (예 : newxpos1 = a + t w)을 가져 와서 거리 공식에 꽂습니다 (양쪽 제곱) : 거리 공식 제곱 = (a + t w-(c + t x)) ^ 2 + (b + t y-(d + t * z)) ^ 2. t는 음수가 될 것임을 기억하십시오. 두 개의 원형 물체에 대한 충돌 시간을 찾기 위해 왼쪽을 (r + s) ^ 2로 설정했습니다. 이차 방정식 (그리고 많은 지루한 대수)을 사용하여 t를 풀면 위의 "t = ..."방정식을 얻게됩니다.

내 질문 :

1) 이것이 좋은 방법입니까? 전혀 작동하지 않습니까? 예기치 않은 문제가 발생합니까? (한 번에 두 개 이상의 물체가 충돌 할 때 문제가 발생한다는 것을 알고 있지만, 실제로 반대하는 유일한 경우는 상대적 속도가 낮을 ​​때입니다 (상대 속도가 높은 경우) 알고리즘이 제공하는 "goofy"솔루션은 "충분히"좋으며, 인간이 오류를 보는 것은 불가능할 것입니다.) 2 개 이상이 동일한 시간 단계에서 낮은 상대 속도와 충돌하면 대부분의 솔루션은 비탄력적인 충돌을 계획하지 않기 때문에 어쨌든 충분히 가까이 있어야합니다.)

2) 성능이 많이 저하됩니까? 나는 그것을하지 않을 것이라고 생각하지만, 그렇게한다면 더 좋은 방법이 있습니까?

3) 2 단계를 건너 뛰고 1 단계에서 3 단계로 바로 가야합니까? 분명히 2 단계는 중요하지 않지만 성능에 도움이 될 수 있습니다 (또는 절약하는 것보다 더 많은 CPU 시간이 소요될 수 있음).

다른 모든 의견, 제안 또는 비판은 매우 환영합니다. 도와 주셔서 감사합니다!


1
Christer Ericson은 주황색 책에 스윕 구 / 구면 테스트에 대한 정보가 있습니다. 이 문제를 해결할 수있는 방법이 몇 가지 있지만 간격을 절반으로 줄이려고합니다. 이 자료를 독자적으로 도출해 보는 것이 좋지만 실제로는 오렌지 북을보고 비교하여 정말 좋은 탐지 루틴을 얻고 더 많은 것을 배우기 위해 비교해야합니다.
RandyGaul

이미 계획이있는 것 같습니다. 시도해보고 작동 방식을 확인 하시겠습니까?
트레버 파월

"일반적인"방법은 델타 시간에 작은 최대 간격을 두는 것입니다. 따라서 1000ms가 경과하면 10x 100ms (또는 100x 10ms 또는 33x 30ms 또는 이와 유사한 것)를 시뮬레이션하십시오.
ashes999

@RandyGaul 215-218 페이지, 특히 218 페이지 (Google 미리보기)에 설명 된 알고리즘을 살펴 보았습니다. 비록 그 의미, 강점 및 약점을 모두 아직 생각하지는 않았지만 매우 우아합니다. 내 것보다 훨씬 빠를까요? 그렇다면 Ericson의 재귀와 비교할 때 알고리즘의 어떤 부분이 느립니까? 3 단계의 방정식이 너무 느려 집니까? 재귀는 주저합니다. 일부 개체가 매우 빠르게 움직일 수 있으므로 경우에 따라 많은 재귀가 필요할 수 있습니다. (또한, OUCH, 그 책에 대한 $ 70 ...)
MindSeeker

1
@MindSeeker 나는 당신의 파생을 살펴볼 시간이 없지만 Ericson의 책에있는 알고리즘 중 어느 것이라도 실제로 잘 작동하고 아마도 당신의 물건보다 더 빠르고 강력 할 것입니다. 다른 페이지를 시연하려면 PDF 버전을 무료로 온라인에서 찾을 수 있습니다. 또한 충돌 감지를 자주 수행하려는 경우 주황색 책은 필수 항목입니다.
RandyGaul

답변:


9

본질적으로 스윕 볼륨 의 다소 과열 된 버전을 작성했습니다 .

물체의 두 위치를 취하십시오. 시작부터 끝까지 개체를 "스윕"합니다. 구의 경우 캡슐이 만들어집니다. 상자의 경우 육각형이 만들어집니다 (또는 상자가 길수록 단일 축을 따라 이동합니다). 일반적인 볼록 다각형의 경우 다른 볼록 다각형이 만들어집니다.

이제이 스윕 된 볼륨을 사용하여 교차 테스트 (쿼드 트리 쿼리 포함)를 수행 할 수 있습니다. 충돌이 발생한 시간을 계산하고 시뮬레이션을 시작 시간에서 충돌 시간으로 롤 포워드 한 후 반복 할 수 있습니다.

다소 간단한 또 ​​다른 옵션은 @ ashes999가 말한 것을 수행하고 더 작은 시간 간격 또는 더 작은 속도를 사용하는 것입니다. 단일 물리 간섭에서 물체가 가장 좁은 면보다 더 멀리 이동할 수없는 간격에서 파생 된 이상적인 최대 속도가 있습니다. 특히 작거나 빠른 물체의 경우 성능이 좋은 작은 간격을 찾지 못할 수 있습니다.

충돌 감지 주제에 대한 더 나은 소개 / 중간 서적 중 하나는 실시간 충돌 감지 를 참조하십시오 .


멋진 의견을 보내 주셔서 감사합니다! 답을 세분화하여 "처음부터 끝까지" "스윕"합니다. " 지금까지 추적 중입니다. 내 박스 방식보다 확실히 개선되었습니다. 이 모양을 quadtree로 공급 한 다음보다 정확한 충돌을 확인합니다. "충돌이 발생한 시점을 계산할 수 있습니다." 하하가 말한 것보다 쉬웠다 :) 당신은 내가 단계 3의 방정식을 고수하는 것이 좋습니다? 아니면 더 좋은 방법이 있습니까? 이것은 정말 중요한 부분입니다.
MindSeeker

[계속] "다른 옵션 ..."해당 옵션에 대해 생각했지만 불행히도 속도가 너무 높습니다. @ ashes999에 대한 내 의견 응답을 참조하고 자세한 내용은 위의 편집하십시오. 당신의 도움을 주셔서 대단히 감사합니다!
MindSeeker

성능에 대해 알 수있는 유일한 방법은 성능을 측정하고 측정하는 것입니다. 나는 "명확하게"비효율적 인 코드가 효율적인 버전보다 성능이 훨씬 뛰어나다는 것을 보았습니다. 가장 빠른 것을 묻지 마십시오. 테스트하고 알아보십시오.
Sean Middleditch

충분히 공정하게 제안한대로 수정하고 내 방법을 시도해 보겠습니다. 주석의 내 질문은 여전히 ​​"충돌이 발생한 시점을 계산할 수 있습니다." 해당 단계에 대해 3 단계의 방정식을 따르는 것이 좋습니다. 아니면 더 좋은 방법이 있습니까? 이것은 내가 생각하는 문제 중 가장 어려운 부분입니다. 스윕 볼륨은 올바르게 이해하면 객체의 경로가 교차하지만 객체 자체가 충돌하는지 여부를 알 수는 없습니다.
MindSeeker

1
@MindSeeker 스윕 지오메트리는 레이 대신 셰이프를 캐스팅하는 것을 제외하고는 레이 캐스팅입니다. 따라서이 방법은 하나의 광선 대 고정 된 물체 대신 모든 빠르게 움직이는 물체에 대해 "선"을 사용한 광선 주조를 사용하는 것과 유사하게 보입니다. "레이"에서 발생할 수있는 충돌을 확인한 후에는 두 "레이"에서 동시에 동일한 지점에 있는지 확인하기 위해 해결해야합니다.
stonemetal

2

문제에서 제안 된 알고리즘은 훌륭하게 작동 합니다. 객체가 극한 속도로 진행되는 경우에도 빠르고 빠릅니다 . 쿼드 트리가 구현되어 있으므로 1 단계의 상자를 쿼드 트리에 공급 한 후 2 단계가 불필요하다는 것을 알았습니다. 내 프로그램이 이전처럼 거의 빠르게 실행되고있었습니다.

나는이 알고리즘을 몇 달 동안 사용해 왔으며 충돌 시간 t를 결정하는 데 완벽하게 정확합니다. 웹에는 더 나은 것이없는 것 같으 므로이 것을 사용하는 것이 좋습니다. (위의 다른 답변과 의견에 대한 답변 중 일부는 훌륭하지만 질문에 명시된 요구 사항을 충족하지 못하거나 저자가 무언가에 대해 매우 모호했으며 모호성에 대해 질문 할 때 다시 대답하지 않았습니다. ).


1

나는 아직 언급할만한 평판이 충분하지 않지만, 위에서 언급 한 Sean Middleditch를 사용하여 "t"를 계산할 수 있다고 덧붙이고 싶습니다. 적어도 내가 그의 대답을 이해하고 당신이 올바르게 질문한다면.

여기에 내가 찾은 것에 대한 최고의 설명을 제공하는 sam hocevar의 멋진 답변에 대한 링크가 있습니다 (그도 그림을 그렸습니다, 만세!)

/gamedev//a/55991/112940

그것이 당신의 방법보다 빠르면 말할 수는 없지만, 그는 그것을 구현하고 당신의 것과 비교하기 위해 필요한 모든 것을 제공합니다.

"링크 전용 답변"을 남기지 않기 위해 그의 아이디어를 요약 해 보겠습니다.

  1. 두 경계 상자 사이의 Minkowski 차이 계산
  2. 그 사이의 상대 속도를 사용하여 교차점을 얻기 위해 원점에서 Minkowski 차이로 만든 상자로 광선 / 선 세그먼트를 캐스트합니다.
  3. 광선이 닿으면 광선이 이동 한 거리를 상대 속도를 나타내는 벡터의 길이로 나누면 "t"가됩니다.
  4. 위에서 제공 한 링크를 클릭하고 많은 그림과 함께이 모든 것에 대한 sam 아름다운 설명을 참조하십시오. 대단해.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.