구와 평면 간의 충돌 응답을 어떻게 계산합니까?


9

간단한 3D 게임을 만들려고하는데 게임 세계의 한계 내에서 플레이어를 제한해야합니다. 플레이어가 월드 사이드에 부딪 칠 때 플레이어의 배가 약간 튀어 오기를 원합니다.

실제로 나는 상자 안에 플레이어를 붙잡고 측면을 빠져 나가는 것을 막으려 고합니다 ...

나는 게임 월드의 한계를 평면과 원점과의 거리와 함께 비행기의 모음으로 정의했습니다. 플레이어는 구형 경계 영역을 가지고 있으며이 웹 사이트를 방문 하면 http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.php 충돌을 감지했습니다.

이제 충돌이 감지되면 어떻게해야하는지 알 수 없습니다. 내가 관리 할 수있는 최선의 방법은 플레이어가 비행기에 갇히거나 똑바로 지나가거나 정말 빠른 속도로 반복적으로 튕기는 것입니다.

상식에 따르면 평면에서 반사 각도를 계산하고 법선을 사용하여 플레이어의 속도에 적용해야한다고 말하지만 플레이어가 내가 할 수없는 비트 인 평면을 통과했는지 먼저 확인해야한다고 생각합니다. 운동하십시오.

답변:


4

물체에 충격을 가해 야합니다. 물체의 속도가 즉시 변화합니다. 실제 세계에서는 매우 짧은 시간 간격으로 물체에 강력한 힘이 가해져 가속도를 반대로하고 속도가 변하게됩니다. 그러나 우리는 별개의 세계에서 일하고 있기 때문에 급격한 방향의 변화를 시뮬레이션하기 위해 약간의 부정 행위가 필요합니다. 구와 평면의 경우 매우 간단합니다. 가장 기본적인 충돌 반응은 평면의 법선 주위에 구의 속도를 반영하는 것이며 결과는 구의 새로운 속도입니다. 의사 코드는 다음과 같습니다.

reflected = 2 * plane.normal * (plane.normal * sphere.velocity)
sphere.velocity -= reflected

거기에서 열이나 마찰로 손실되는 에너지를 설명하기 위해 약간의 감쇠 (0.9와 같은 계수를 곱함)를 추가 할 수 있습니다. 각속도를 구하고 싶다면 (구가 회전하고있을 수도 있음) 방정식이 조금 더 복잡해집니다.

자세한 내용은 Rigid Body Dynamics 에 관한 Chris Hecker의 기사를 참조하십시오 . Chris Hecker에 대해 들어 본 적이 없다면 게임 물리학 및 Spore의 절차 적 캐릭터 생성 및 애니메이션 관련 작업으로 잘 알려져 있습니다.


4
이것은 본질적으로 올바른 방법이지만, TOI (Time of Impact)를 계산하면 프레임 속도가 변동하거나 떨어질 때 상황이 더 정확해질 수 있습니다. 현재 속도를 기준으로 충격이 발생한 시간을 알면 충격 시간을 계산하는 데 도움이되며이를 사용하여 구를 충격 순간의 위치로 다시 이동하고 속도를 조정할 수 있습니다. 충격 시점에서 충격 지점에서 위치와 속도를 조정 한 후 공제 된 시간만큼 TOI에 도달하기 위해 새로운 속도를 따라 이동합니다.
Nic Foster

좋아 이것은 대부분 작동하는 것처럼 보이지만 조금 이상합니다. 내 코드의 잘못된 지점 에서이 작업을 수행하고 있다고 생각합니다. 모든 객체를 반복하고 객체를 이동하기 전에 (다음 프레임이 될 위치를 기준으로) 충돌하는지 테스트 한 다음 이동 한 다음 충돌을 테스트해야합니까?
Piku

@Piku, 충돌하는지 감지하지 않습니다. 충돌이 발생하면 두 개체가 실제 충돌이 발생한 위치를 훨씬 넘어서 겹쳐 질 가능성이 매우 높다는 것을 기억하십시오. 무한 프레임 속도 (없는 프레임)를 가진 것처럼 충돌이 발생한 위치를 파악하고 충돌이 처음 발생한 위치로 객체를 다시 이동해야합니다. 이와 같이 오브젝트를 분리하지 않으면 동일한 충돌에 지속적으로 반응하여 오브젝트가 고착됩니다.
Jonathan Dickinson

@Piku와 그렇게하기 위해 과거에 충돌이 발생한 시간 (TOI / 충격 시간)을 알아 냈습니다. 일단 우리는 물체의 속도를 사용하여 물체를 뒤로 이동시키고 ( distance = speed * time일반적으로 오차를 피하기 위해 아주 작은 거리로) 충돌 결과의 속도로 속도를 업데이트 할 수 있습니다.
Jonathan Dickinson

@Piku는 또한 다음 프레임의 위치를 ​​파악하지 못하지만 (개인적으로는 본 적이 없습니다) 일반적으로 충돌 감지 및 응답을 수행합니다.이 프레임의 새 위치를 계산 한 후에는이 전에 이 프레임에 새로운 위치를 적용합니다.
Jonathan Dickinson

1

F = ma 또는 a = F / m. 구와 평면 사이의 충돌 지점을 계산하십시오. 일반적으로 구 중심-법선 * 반경입니다. 정확도를 높이려면 구가 평면에 얼마나 멀리 침투했는지 계산하고 계산을 조정하십시오. 당신이 정말로 정확한 물리학을 원하지 않는다면, 이것은 물론 선택 사항입니다. 이제 법선을 따라 상대 속도를 계산하십시오. 정적 평면의 경우 : Vball Dot N입니다. 그런 다음 VballDotN에 -1을 곱하고 질량을 곱합니다. 이 단계의 물리에서는이 계수에 반발 계수 (반송 계수)를 곱할 수도 있습니다. 이 스칼라에 N을 곱하면 힘이 있습니다.

Vball을 조정할 때 힘을 다시 질량으로 나누면 최종 가속이 있으므로 속도에 추가하면 최종 사후 충돌 속도가됩니다.

vec3 Vrel = Ball.getVelocity();
float vDotN = Vrel.Dot(CollisionNormal);
vec3 F = -(1.0f+Ball.getRestitution())*vDotN;
F*=Ball.getMass();
Ball.accelerate(F/Ball.getMass());

이 방법은 충돌 반응 공식에 정확합니다. 더 정확한 정확도를 원한다면 마찰을 고려하여 공이 회전하지만 게임에서 원하는지 모르겠습니다. 이 경우 접선 력을 계산하는 방법입니다.

vec3 Ft = -(Ball.getvelocity()+(vDotN*CollisionNormal));
Ft*=Ball.getKineticFriction()+Wall.getKineticFriction(); //you could fudge these numbers
Ft*=Ball.getMass();
vec3 vec2Centre = Ball.getPosition()-ContactPoint;
vec3 Torque = cross(vec2Centre,Ft);
Ball.AngularAccelerate(Torque/Ball.getMomentofInertia(glm::normalize(Torque)));

선형 효과를 적용하기 전에 Ft를 계산하십시오. 그렇지 않으면 마찰이 정확하지 않습니다.


3 행은 안됩니다 : vec3 F = -CollisionNormal * (1.0f+Ball.getRestitution())*vDotN;?
Shital Shah

실제로 그렇습니다, 나는 그 부분을 놓쳤다. 지적 해 주셔서 감사합니다.
이안 영

0

먼저 비행기와의 거리를 계산하는 것이 좋습니다. 그리고 거리 <=에서 반경까지 일 때 충돌 반응을 수행한다.

그런 다음 거리를 계산하도록 거리를 변경하고 거리가 반경보다 작은 경우 (물체가 겹치는 것을 의미 함) 볼 위치를 이동 한 다음 충돌 반응을 수행 할 수 있습니다.

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