태그 보관물: physics

physics

힘과의 충돌 해결 수동으로 위치에서 작업하거나

내 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에서 확인할 수 있습니다.



답변

먼저 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 개 이상의 물체와 같은 다른 경우에는 전체 뉴턴 운동 방정식 (운동량 보존 및 운동 에너지 보존)을 풀어야합니다.
  • 운동에 대한 뉴턴 식 방정식이 두 개 이상의 몸체에 대해 풀 수 있는지 확실하지 않습니다. 그러나 다행히도 세 가지 물체가 거의 동시에 충돌하지는 않습니다. 충돌하는 처음 두 바디를 처리 한 다음 이전 충돌 해상도의 새로운 속도를 사용하여 다음 충돌을 처리하면 충분합니다. 이것은 물리 시간 단계를 가능한 한 작게 유지하고 침투가 발생하기 전에 충돌을 처리하는 좋은 이유입니다.
  • 내 소행성 데모에서 더 큰 바위가 작은 바위로 나뉘어 짐에 따라 많은 시체가 만들어집니다. 그러나 나는 항상 신체 쌍 사이의 충돌을 처리합니다. 두 개 이상의 바디와의 충돌을 명시 적으로 처리하지 마십시오.

답변

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

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

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

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

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


답변

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

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

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

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

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


답변