힘과의 충돌 해결


14

내 2D 물리 엔진에서 AABB 대 AABB 충돌을 감지하고 가장 짧은 침투 벡터를 찾아 AABB 위치에 추가하여 해결할 수 있습니다.

이 작업을 수행하면 두 번째 AABB 외부의 첫 번째 AABB가 "푸시"되지만 속도 / 가속 변경은 처리되지 않습니다.

시뮬레이션에 중력 가속을 추가하면 첫 번째 동적 AABB의 속도가 두 번째 정적 AABB 위에있을 때도 계속 증가합니다. 결국 속도가 너무 커지고 충돌이 감지되지 않습니다 (동적 AABB는 정적 속도를 fall습니다).

해상도 후 속도를 0으로 설정하려고 시도했지만 분명히 잘 작동하지 않았으며 비현실적인 시뮬레이션을 만들었습니다.

나는 수동으로 위치에서 작업하거나 속도가 정확하지 않다는 것을 온라인으로 읽었습니다. 나는 힘을 구현하려고 시도했다 (질량은 "하드 코딩 된"1이다) :

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

충돌 해결 중 가장 짧은 관통 벡터를 힘으로 적용하면 동적 AABB는 정적 것으로부터 "밀어 내"지지만, 중력이없는 시뮬레이션에서는 속도가 절대로 감소하지 않으며 영원히 계속 움직입니다.

"임시"힘을 적용 할 수있는 방법이 있습니까? AABB가 더 이상 충돌하지 않으면 첫 번째 AABB를 두 번째 AABB에서 밀어내는 힘이 작용합니까?

전체 소스 코드는 https://github.com/SuperV1234/SSVSCollision에서 확인할 수 있습니다.


1
나는 이것에 관심이있다. 아직 해결책을 찾았습니까?
TravisG

@TravisG : 아직 안타깝게도. 답장이 없으면 내일 현상금을 추가하겠습니다.
Vittorio Romeo

힘은 우선 가속과 같지 않습니다. 가속도를 계산하려면 질량이 필요합니다. 두 바디의 침투를 막기 위해 위치를 수정하는 경우 질량도 사용하고 그에 따라 두 바디를 이동해야합니다. 침투 벡터와 같은 힘을 가해도 아무런 장점이 없습니다. Box2D는 임펄스 기반이며, 속도에서 직접 작동하며, "올바르지"않을 수도 있지만 충분합니다. 임펄스 기반 엔진의 속도 변화를 다루는 것은 매우 간단하므로 포스 기반 솔루션을 확실히 원하는지 또는 훨씬 더 간단한 임펄스 기반 솔루션인지를 지정할 수 있습니다.
dreta

개인적으로, 나는 물리 엔진에 관한 책을 고르는 것을 제안하고 적어도 뉴턴 물리학에 관한 처음 몇 장을 읽습니다. 당신의 가정이 부정확하고이 질문에 답하려고하면 충돌의 해결을위한 높은 수준의 알고리즘을 설명하면서 물리의 기초를 가르쳐야합니다.
dreta

@dreta 그의 가정은 괜찮습니다. 그는 모든 객체의 질량이 현재 "1"이므로 코드 섹션이 유효하다고 지적했습니다. 그건 그렇고, Box2D가 속도를 직접 처리 할 수는 있지만 어떻게 든 동일한 문제를 처리해야합니다. 힘을 가하는 대신 Box2D는 충격을 가하지 만, 일단 물체가 분리되면 충격이 사라지지 않는다는 사실을 처리해야합니다. 그러나 실제로이 문제를 전혀 처리하지 않고 물체가 에너지를 유지할 수있게 할 수도 있습니다 (결국 실제 세계에서는 이와 같을 것입니다)
TravisG

답변:


13

먼저 Box2D 와 같은 무료 오픈 소스 물리 라이브러리 를 사용하고 게임의 고유 한 특징에 집중 하는 것이 좋습니다 ! 휠을 재발 명 할 것을 요구한다면, 계속 읽어보십시오 ... 모든 물리 엔진은 근사치이며 아래에 설명 된 방법이 현재 모델보다 더 정확하지만 Box2D의 결과는 훨씬 더 현실적입니다.


두 객체 A와 B의보다 정확한 충돌 해결을 모델링하는 빠른 방법 :

  1. 충돌 직전 위치를 찾으십시오. "가장 짧은 침투 벡터를 찾아 AABB의 위치에 추가"하여 이미 근사치입니다.
  2. 뉴턴 물리학을 사용 하여 충돌 직후의 속도를 찾으십시오 .
    • 질량이 1로 하드 코딩 된 경우, 간단히 속도를 바꾸십시오 (무한 질량을 가져야하는 정적 객체에는 적용되지 않음).
      • Av = Bu
      • Bv = Au
    • 객체 A와 B의 질량이 다른 경우 :
      • Av = (Au * (Am-Bm) + (2 * Bm * Bu)) / (Am + Bm)
      • Bv = (Bu * (Bm-Am) + (2 * Am * Au)) / (Am + Bm)
    • 어디:
      • v : 충돌 후 속도
      • u : 충돌 전 속도
      • m : 질량 (고정 된 정적 물체의 질량에 가능한 최대 개수 사용)
  3. 가속도를 0으로 설정 합니다. 충돌로 인한 가속도는 2 단계의 속도 계산에 의해 계산되었습니다.

이러한 개념을 보여주는 샘플 소행성 프로그램 을 살펴보십시오 .


다음으로 쌓인 물체를 설명하십시오.

앞서 언급했듯이, 속도를 사용하여 쌓인 / 휴식 물체를 시뮬레이션하는 것은 효과가 없습니다. 정지 상태에있는 물체의 속도 :

시뮬레이션에 중력 가속을 추가하면 첫 번째 동적 AABB의 속도가 두 번째 정적 AABB 위에있을 때도 계속 증가합니다. 결국 속도가 너무 커지고 충돌이 감지되지 않습니다 (동적 AABB는 정적 속도를 fall습니다).

실제로 일어나는 것은 중력이 중력을 상쇄시켜야하므로 반대 방향으로 진행하는 가속력입니다. (정상 접촉력이라고합니다). 지름길은 단순히 공중에 있지 않은 몸에 중력을 가하지 않는 것입니다.

  • 이를 수행하는 한 가지 방법은 "접지"상태를 유지하는 것입니다.
    • 접지 된 상태의 물체에 중력을 가하지 마십시오.
    • 물체가 아래에서 물체와 충돌하고 속도가 매우 작은 경우 접지 상태로 들어갑니다.
    • 수직 속도가 특정 양수 값을 초과하면 객체가 접지 상태를 종료합니다.

최신 정보:

  • 평신도의 관점에서, 뉴턴 물리학은 충돌 전후의 총 에너지가 일치해야한다고 말합니다. 두 물체가 서로 충돌하면 에너지가 재분배됩니다. 에너지는 속도와 무게의 조합입니다. 무겁고 빠를수록 더 많은 에너지를 얻습니다. 직관적입니다. 그러나 직관적이지 않은 것은 가중치가 에너지 재분배에 영향을 미치는 정확한 방법입니다.
  • 스와핑 속도는 동일한 질량을 갖는 두 개의 고정되고 고정되지 않은 바디에 대한 지름길입니다 (정적 고정 오브젝트는 매우 크고 무한한 질량을 가짐).
  • 하나의 정적 바디가 고정 될 때의 지름길은 다음과 같습니다. 다른 동적이고 고정되지 않은 바디는 같은 속도를 유지합니다. 각도 만 변경됩니다 (볼이 레일에 닿을 때 당구대를 상상해보십시오. 레일은 기본적으로 매우 크고 무한한 질량을가집니다).
  • 3 개 이상의 물체와 같은 다른 경우에는 전체 뉴턴 운동 방정식 (운동량 보존 및 운동 에너지 보존)을 풀어야합니다.
  • 운동에 대한 뉴턴 식 방정식이 두 개 이상의 몸체에 대해 풀 수 있는지 확실하지 않습니다. 그러나 다행히도 세 가지 물체가 거의 동시에 충돌하지는 않습니다. 충돌하는 처음 두 바디를 처리 한 다음 이전 충돌 해상도의 새로운 속도를 사용하여 다음 충돌을 처리하면 충분합니다. 이것은 물리 시간 단계를 가능한 한 작게 유지하고 침투가 발생하기 전에 충돌을 처리하는 좋은 이유입니다.
  • 내 소행성 데모에서 더 큰 바위가 작은 바위로 나뉘어 짐에 따라 많은 시체가 만들어집니다. 그러나 나는 항상 신체 쌍 사이의 충돌을 처리합니다. 두 개 이상의 바디와의 충돌을 명시 적으로 처리하지 마십시오.

자세한 답변에 감사드립니다. 나는 이해하지 못하는 것이 있습니다 : 속도를 바꾸는 것은 2 개의 몸체와의 충돌에서 잘 작동합니다. 그러나 여러 몸체 (및 정적 몸체)가 동시에 충돌 할 때 어떻게 작동하는지 알 수 없습니다. 중력이 없어도 동적 몸체가 정적 몸체와 동시에 충돌하면 다른 동적 몸체가 문제를 일으 킵니다. 속도가 바뀌기 때문에 충돌 순서에 따라 달라집니다. 정적 바디가 마지막에 충돌하면 바디가 이동을 멈 춥니 다. 동적 인 것이면 몸은 다시 움직입니다. 이 문제는 어떻게 해결됩니까?
Vittorio Romeo

@Vee : 좋은 질문입니다! Three + body와 static body는 별개의 문제입니다. 나는 업데이트에서 둘 다 해결했다. 요약 : 한 번에 두 객체의 충돌을 처리합니다. 정적 몸체는 매우 크고 무한한 질량을가집니다.
Leftium

휴면 접점 모델이 이상합니다. 휴식 접점은 중력만을위한 것이 아니라 어떤 힘에도 작용해야합니다. 가장 쉬운 방법은 접촉시 이전 프레임의 가속으로 인해 얻은 속도를 제거하는 것입니다. 또한 작은 속도의 경우 계산에서 배상을 설명하지 않지만 배상을 완전히 제거 할 수 있습니다. 이 접근 방식은 모든 힘에 적용되며 구현하기 쉽고 충분히 좋아 보입니다.
dreta

16

이 문제를 해결하려면 위치와 속도를 조정해야합니다. 리지드 바디 물리 엔진에는 뉴턴의 운동 법칙을 사용하여 물체를 제 시간에 전진시켜 비 침투 제약과 마찰을 해결하는 솔버가 있습니다. 이 엔진은 선형 및 각도 운동의 올바른 조합을 계산하여 그럴듯한 궤적을 생성 할 수 있습니다.

오버랩 만 해결하려면 모멘텀에 추가하지 않고 분리 궤적을 생성하는 의사 속도를 사용할 수 있습니다. 이것은 Box2D의 위치 솔버에서 수행됩니다.

2006 년과 2007 년부터 GDC 프레젠테이션을받는 것이 좋습니다.

http://code.google.com/p/box2d/downloads/list

또한 단순화 된 구현을 위해 Box2D Lite를 볼 수 있습니다.


위치를 조정할 필요가 있다는 말에 +1. 이 점에 빠지는 사람은 거의 없지만 시뮬레이션 안정성을 높이기 위해 대부분의 엔진은 위치를 직접 조정하여 속임수를 사용합니다. 대체로 그것이 그럴듯하다면 게임에도 효과적입니다.
teodron

답변 해주셔서 감사합니다. 프레젠테이션에서 놓친 부분을 알고 싶었습니다. Box2D에서 정적 몸체가 특별한 방식으로 처리됩니까? 다이나믹 바디가 정적 바디에 닿으면 어떻게됩니까?
Vittorio Romeo

2

여기에 이미지 설명을 입력하십시오

실제 세계에서는 물체가 서로 관통하지 않기 때문에 한 몸체를 다른 몸체 외부로 "밀어내는"힘이 없습니다. 가장 가까운 것은 법선 힘입니다 . 실제 충돌에서 접촉하는 순간에 생성되어 처음부터 침투하는 것을 방지합니다.

이 수직력의 각도는 두 충돌 물체의 접촉 표면에 수직입니다. 그 크기는 침투를 막기 위해 얼마나 많은 힘이 필요한지에 달려 있습니다. (마찰력과 같은 다른 힘도 모델링하지 않는 한 수직력의 y 성분 만 사용해야합니다).

수직력을 명시 적으로 모델링하는 것이 가능하지만 그 효과 만 모델링하는 것이 더 간단합니다.

  1. 다음 중 하나를 수행하여 객체 교차를 방지하십시오.
    • 충격 순간 충돌을 해결하여 속도를 조정합니다. (베스트)
    • 교차하지 않도록 바디의 위치를 ​​수동으로 조정합니다. 당신은 이미 "가장 짧은 침투 벡터를 찾아 AABB의 위치에 추가함으로써"이것을하고 있습니다.
  2. 중력을 상쇄시키는 수직력이있는 곳에 중력을 가하지 마십시오.
    • 그 아래의 다른 물체와 접촉하는 물체는 수직력을받습니다. 따라서 이러한 객체를 추적하는 것이 중요합니다. (실제로 접촉하는 모든 물체에는 수직 힘이 가해 져야하지만 이들 중 일부가 중력과 관련하여 순 영향을 미치지는 않습니다.)
    • 비스듬한 다른 물체를 아래로 미끄러 뜨릴 수있는 물체를 추가하려면, 마찰력과 수직 힘의 x 성분을 추가해야합니다.

나는 일반적인 충돌에 대한 다른 답변 에서 이것을 약간 다르게 설명 했다 .

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