번역
====================
The Basics and Impulse Resolution
너가 custom physics engine을 만들길 원하는 이유는 많은 이유들이 있다 : 첫 번째, 수학, 물리 그리고 프로그래밍에서 너의 갈고 닦는 것은 그러한 프로젝트를 시도할 훌륭한 이유이다; 둘 째로, custom physics engine은 만드는 사람이 만들 기술가지고 있다면 어떤 종류의 기술적 효과든지 다룰 수 있다. 이 자료에서, 나는 처음 부터 어떻게 전적으로 custom physics engine을 만들지에 대해 탄탄한 소개를 제공할 거시앋.
물리하은 한 플레이어가 게임 내에서 그들 자신을 빠져들게 하는 훌륭한 수단을 제공한다. 그것은 물리 엔진의 matery가 어떤 프로그래머가 그들 마음대로 하게 하는 강력한 자산이 될 것이라는 의미이다. 최적화와 특수화는 물리 엔진의 내부 작동의 깊은 이해에 의해 언제든지 만들어질 수 있다.
이 튜토리얼의 끝에서, 다음의 주제들이 다루어질 것이다, 2차원에서:
- Simple Collision Detection
- Simple Manifold Generation
- Impulse Generation
여기에서 빠른 데모가 있다:
Note : 비록 이 튜토리얼들이 C++를 사용하여 작성될지라도, 너는 거의 어떤 게임 개발 환경에서 든지 같은 기법들과 개념들을 사용할 수 있어야 한다.
Prerequisites
이 자료는 많은 양의 수학과 기하학을 포함하고, 더 작은 범위로 실제 코딩을 포함한다. 이 자료에 대해 두 가지 미리 요구조건은:
- A basic understanding of simple vector math
- The ability to perform algebraic math
Collision Detection
인터넷 도처에 Tuts+를 포함하여, 충돌 탐지를 다루는 꽤 많은 자료들과 튜토리얼들이 있다. 이것으 ㄹ아고나서, 나는 그 주제에 대해 빠르게 들어가고 싶다, 이 섹션은 이 자료의 중점이 아니기 때문이다.
Axis Aligned Bounding Boxes
AABB는 그것의 4개의 축을 갖는데, 그것이 있는 좌표계에 정렬되어 있다. 이것은 회전할 수 없는 박스라는 것을 의미하고, 항상 90도로 squared off되어있다는 것을 의미한다 (보통 screen과 정렬되어 있다). 일반적으로, "bounding box"라고 언급이되는데, AABB가 다른 좀 더 복잡한 shapes들을 bound시키는데 사용되기 때문이다.
complex shape의 AABB는 AABB안의 좀 더 복잡한 도형들이 가급적 교차하고 있는지를 보는 간단한 테스트로서 사용되어질 수 있다. 그러나, 대부분의 게임의 경우에, AABB는 기본 도형으로 상요되고, 실제로 어떤 다른 것을 bound하지 않는다. 너의 AABB의 구조는 중요하다. AABB를 나타내는 몇 가지 다른 방법들이 있지만, 이것이 내가 가장 좋아하는 것이다:
이것은 AABB가 두 점에 의해 나타내어지는 것을 가능하게 한다. min point는 x와 y축의 lower bounds를 타나개ㅗ, max는 더 높은 bounds를 나타낸다 - 다시 말해서, 그것들은 top left와 bottom right corenrs를 나타낸다. 두 개의 AABB shapes가 교차하고 있는지를 구분하기 위해서, 너는 Separating Axis Theorem(SAT)의 기본적인 이해를 가질 필요가 있을 것이다.
여기에 RTCD로부터 가져와진 빠른 테스트가 있다. 이것은 SAT를 이용한다:
Circles
원은 radius와 point로 나타내어진다. 여기에서 너의 원의 구조체가 어떻게 보이는지가 있다:
두 개의 원이 교차하는지를 테스트하는 것은 매우 간단하다: 두 개의 원의 반지름을 취하고, 그것들을 더하고, 이 합이 두 원 사이의 거리보다 더큰 지를 보아라.
한 중요한 최적화는 여기에서 square root operator를 사용하는 것을 제거하는 것이다:
일반적으로 곱이 한 값의 제곱근을 취하는 것보다 더 싼 연산이다.
Impulse Resolution
Impulse resolution은 Collision resolution strategy의 특별한 유형이다. Collision Resolution은 충돌하고 있다고 알려진 두 개의 오브젝트들을 취해서 그것들이 교차하지 않도록하는 방식으로 그것들을 수정하는 것이다.
일반적으로 물리 엔진에서 한 오브젝트는 3 개의 DoF를 갖는다 (이차원에서): xy 평면에서의 움직임과 회전. 이 자료에서, 우리는 implicitly하게 회전을 제한하고, 그냥 AABB와 원만을 사용한다. 그래서 우리가 고려해야할 필요가 있는 유일한 자유도는 xy평면에서의 움직임이다.
탐지된 충돌을 해결하여, 우리는 움직임에 제한을 배치하는데, 오브젝트들이 서로 교차할 수 없게 하도록 한다. impulse resolution 뒤에 있는 아이디어는 충돌하고 있다고 발견된 오브젝트들을 분리하기 위해 impulse (즉각적인 속도에서의 변화)를 사용하는 것이다. 이것을 하기 위해서, 각 오브젝트의 질량, position, velocity가 어느정도 취해져야 한다: 우리는 더 작은 것과 충돌하는 더 큰 오브젝트들이 충돌동안 조금 움직이기를 원하고, 그 작은 오브젝트들을 멀리 보내기를 원한다. 우리는 또한 무한의 질량을 가진 오브젝트들이 움직이지 않기를 원한다.
그러한 효과를 성취하고, 어떻게 오브젝트들이 행동하는지에 대한 자연적인 직관을 따르기 위해서, 우리는 rigid bodies를 사용할 것이고, 조금의 수학을 사용할 것이다. rigid body는 사용자에 의해 정의된 shape인데 (즉, 너에 의해서, 개발자) implicitly하게 변형될 수 없다고 정의된다. 이 자료에서 AABB와 Circles 둘 다 non-deformable하고, 항상 AABB or Circle 둘 중 하나가 될 것이다. 어떠한 squashing or stretching이 허용되지 않는다.
rigid bodies로 작업하는 것은 많은 수학과 유도들이 많이 간단하게 한다. 이것은 게임 시뮬레이션에서 rigid bodies가 흔히 사용되는 이유이고, 우리가 그것들을 이 자료에서 사용할 것이다.
Our Objects Collided - Now What?
우리가 두 shapes가 교차하고 있다고 알려진다고 가정하면, 어떻게 우리는 그 두 개를 분리하는가? 우리의 충돌 탐지가 우리에게 두 가지 중요한 정보를 줬다고 가정하자:
rigid bodies로 작업하는 것은 많은 수학과 유도들이 많이 간단하게 한다. 이것은 게임 시뮬레이션에서 rigid bodies가 흔히 사용되는 이유이고, 우리가 그것들을 이 자료에서 사용할 것이다.
Our Objects Collided - Now What?
우리가 두 shapes가 교차하고 있다고 알려진다고 가정하면, 어떻게 우리는 그 두 개를 분리하는가? 우리의 충돌 탐지가 우리에게 두 가지 중요한 정보를 줬다고 가정하자:
- Collision normal
- Penetration depth
두 오브젝트들에 impulse를 적용하기 위해서, 그리고 그것들을 떨어져서 움직이게 하기 위해서, 우리는 그것들을 무슨 방향으로 밀어낼지를 알 필요가 있다. 그리고 얼마나 많이. collision normal은 impulse가 적용되는 방향이다. 그 penetration depth는 (어떤 다른 것을 따라) impulse가 얼마나 많이 사용될지를 결정한다. 이것은 해결될 필요가 있는 유일한 값이 우리의 impulse의 크기이다.
이제, 우리가 어떻게 이 impulse magnitude에 대해 해결할 수 있는지를 발견해보자. 우리는 우리의 두 개의 오븢게트들이 교차하고 있따고 발견된것으로 시작할 것이다:
Equation1
V^AB = V^B - V^A
위치 A에서 위치 B로가는 벡터를 만들기 위해서, 너는 endpoint - startpoint를 해야한다는 것에 주목해라: V^AB는 A에서 B로 가는 relative velocity이다. 이 방정식은 collision normla n의 관점으로 표현되어야 하는데, 즉, 우리는 collision normal의 방향을 따라 A에서 B로 가는 relative velocity를 알고싶다:
Equation 2
Dot(V^AB, n) = Dot(V^B - V^A, n)
우리는 내적을 사용할 것이다. 그 내적은 간단하다; 그것은 component-wise products의 합이다:
Equation 3
그 다음 단계는 restitution 계수라고 불리는 것을 도입하는 것이다. Restitution은 탄성 또는 bounciness를 의미하는 항이다. 너의 물리엔진에서 각 오브젝트는 decimal value로서 나타내어지는 restitution을 가질 것이다. 그러나, impulse calculation 동안 오직 한 개의 decimal value가 사용될 것이다.
(epsilon에 대해 e라고 표기되는) 무슨 restitution을 사용할지를 결정하기 위해, 너는 항상 직관적인 결과를 위해 충돌과 관련되어 가장 낮은 restitution을 사용해야할 것이다:
// Given two objects A and B
e = min(A.restitution, B.restitution)
일단 e가 얻어지기만 한다면, 우리는 그것을 impulse magnitude를 풀기위한 방정식에 넣는다.
뉴튼의 Restitution 법칙은 다음과 같이 주장한다:
Equation 4
V' = e * V
이것이 말하는 모든 것은 충돌 후의 속도가 그것을 하기 전의 속도와 같은데, 어떤 상수로 곱해진다는 것이다. 이 상수는 "bounce factor"를 나타낸다. 이것을 알고나서, restitution을 우리의 현재 derivation에 통합하는 것은 꽤 쉽다:
Equation 5
Dot(V^AB, n) = -e * Dot(V^B - V^A, n);
우리가 여기에서 음수 기호를 어떻게 도입했는지를 주의해라. 뉴턴의 Restitution 법칙에서, bounce 후의 결과 벡터인 V'는 실제로 V의 반대 방향으로 가고 있다. 그래서 우리는 어떻게 우리의 derivation에서 반대 방향을 나타내는가? 음수 기호를 넣어라.
지금까지는 좋다. 이제 우리는 이러한 속도들을 표현할 수 있는데, 한 impulse의 영향하에 있으면서. 여기에 특정한 방향 n을 따라 어떤 impulse scalar j에 의해 한 벡터를 수정하는 간단한 방정식이 있다:
Equation 6
V' = V + j * n
희망스럽게도, 위의 방정식은 이해가 된다, 그것은 이해하기에 매우 중요하다. 우리는 방향을 나타내는 단위 벡터 n을 가지고 있다. 우리는 우리의 n이 얼마나 길지를 나타내는 스칼라 j를 가진다. 우리는 그러고나서 우리의 scaled n vector를 V에 더해서 V'를 만든다. 이것은 한 벡터를 다른 것에 더하는 것이고, 우리는 이 작은 박정식을 한 벡터의 impulse를 다른 것에 적용하는데 사용할 수 있다.
여기에서 해질 필요가 있는 더 많은 일이 있다. 공식적으로 impulse는 momentum에서 변화라고 정의된다. Momentum은 mass * velocity이다. 이것을 알고나서, 우리는 impulse를 그것이 그렇게 정의되어되는 것처럼 나타낼 수 있다:
Equation 7
Impulse = mass * Velocity
Velocity = Impulse / mass
V' = V + (j * n) / mass
좋은 progress가 여기까지 만들어졌다! 그러나, 우리는 두 개의 다른 오브젝트들의 관점에서 j를 사용하여 impulse를 사용할 필요가 있다. 오브젝트 A와 B의 충돌 동안, A는 B의 반대 방향으로 밀어질 것이다:
Equation 8
V'^A = V^A + (j * n) / mass^A
V'^B = V^B - (j * n) / mass^B
이러한 두 방정식들은 A를 B로부터 밀어낼 것이다, 단위 벡터 n의 방향을 따라, impulse scalar (n의 크기) j 만큼.
이제 요구되는 것은 방정식 8과 5를 합치는 것이다. 우리의 최종 방정식은 이것처럼 보일 것이다:
Equation 9
Dot(V^A - V^B + (j * n) / mass^A + (j * n) / mass^B), n) = -e * Dot(V^B - V^A, n)
만약 너가 회상한다면, 원래 목표는 우리의 크기를 isolate하는 것이였다. 이것은 왜냐하면 우리는 그 충돌을 어떤 방향으로 해결할지를 알기 때문이다 (충돌 탐지에 의해서 주어진다고 가정하여), 그리고 이 방향의 크기를 해결하도록 남기는 것이다. 우리의 경우에 미지수인 크기는 j이다, 우리는 j를 isolate하여 그것에 대해 푼다.
우리가 여기에서 음수 기호를 어떻게 도입했는지를 주의해라. 뉴턴의 Restitution 법칙에서, bounce 후의 결과 벡터인 V'는 실제로 V의 반대 방향으로 가고 있다. 그래서 우리는 어떻게 우리의 derivation에서 반대 방향을 나타내는가? 음수 기호를 넣어라.
지금까지는 좋다. 이제 우리는 이러한 속도들을 표현할 수 있는데, 한 impulse의 영향하에 있으면서. 여기에 특정한 방향 n을 따라 어떤 impulse scalar j에 의해 한 벡터를 수정하는 간단한 방정식이 있다:
Equation 6
V' = V + j * n
희망스럽게도, 위의 방정식은 이해가 된다, 그것은 이해하기에 매우 중요하다. 우리는 방향을 나타내는 단위 벡터 n을 가지고 있다. 우리는 우리의 n이 얼마나 길지를 나타내는 스칼라 j를 가진다. 우리는 그러고나서 우리의 scaled n vector를 V에 더해서 V'를 만든다. 이것은 한 벡터를 다른 것에 더하는 것이고, 우리는 이 작은 박정식을 한 벡터의 impulse를 다른 것에 적용하는데 사용할 수 있다.
여기에서 해질 필요가 있는 더 많은 일이 있다. 공식적으로 impulse는 momentum에서 변화라고 정의된다. Momentum은 mass * velocity이다. 이것을 알고나서, 우리는 impulse를 그것이 그렇게 정의되어되는 것처럼 나타낼 수 있다:
Equation 7
Impulse = mass * Velocity
Velocity = Impulse / mass
V' = V + (j * n) / mass
좋은 progress가 여기까지 만들어졌다! 그러나, 우리는 두 개의 다른 오브젝트들의 관점에서 j를 사용하여 impulse를 사용할 필요가 있다. 오브젝트 A와 B의 충돌 동안, A는 B의 반대 방향으로 밀어질 것이다:
Equation 8
V'^A = V^A + (j * n) / mass^A
V'^B = V^B - (j * n) / mass^B
이러한 두 방정식들은 A를 B로부터 밀어낼 것이다, 단위 벡터 n의 방향을 따라, impulse scalar (n의 크기) j 만큼.
이제 요구되는 것은 방정식 8과 5를 합치는 것이다. 우리의 최종 방정식은 이것처럼 보일 것이다:
Equation 9
Dot(V^A - V^B + (j * n) / mass^A + (j * n) / mass^B), n) = -e * Dot(V^B - V^A, n)
만약 너가 회상한다면, 원래 목표는 우리의 크기를 isolate하는 것이였다. 이것은 왜냐하면 우리는 그 충돌을 어떤 방향으로 해결할지를 알기 때문이다 (충돌 탐지에 의해서 주어진다고 가정하여), 그리고 이 방향의 크기를 해결하도록 남기는 것이다. 우리의 경우에 미지수인 크기는 j이다, 우리는 j를 isolate하여 그것에 대해 푼다.
j = -(1+e)(Dot(V^B - V^A, n)) / ( 1/mass^A + 1/mass^B )
마지막 방정식 10의 버전에서, j가 왼쪽에 있고, 모든 것이 오른쪽에 있다. 이것은 우리가 impulse scalar j를 풀기 위해 몇 줄의 코드를 쓸 수 있다는 것을 의미한다.
위의 코드 샘플에서 주목해야할 몇 가지 것들이 있다. 첫 번쨰 것은 Line 10에서 체크이다. 이 체크는 매우 중요하다; 그것은 너가 objects가 서로를 향하고 있다면 collision을 해결하도록 한다.
만약 오브젝트들이 서로에게 멀어지고 있다면, 우리는 아무것도 하기를 원하지 않느다. 이것은 실제로 충돌하고 있다고 고려되지 않아야 할 오브젝트들이 서로에대해 resolving되는 것을 방지한다. 이것은 사람의 직관을 따르는 시뮬레이션을 만드는데 중요하다. 그 직관은 오브젝트 상호작용 동안 무엇이 발생하는가에 대한 것이다.
주목해야될 두 번째 것은, inverse mass가 이유없이 여러번 연산되는 것이다. 각 오브젝트 내에 inverse mass를 저장하여, 그것을 한 번 미리 연산하는 것이 가장 좋다:
많은 물리엔진들은 실제로 raw mass를 저장하지 않는다. 물리엔진은 종종 inverse mass * time 그리고 inverse mass를 홀로 저장한다. 그래서 질량과 관련된 대부분의 수학이 1/mass의 형태로 있다. 주목해야 할 마지막 것은 우리가 지능적으로 우리의 impulse scalar j를 두 오브젝트에 대해 분산하는 것이다. 우리는 작은 오브젝트들이 큰 오브젝트에 대해 큰 j의 부분으로 튕겨 나가기를 원하고, 큰 오브젝트들은 그것들의 속도가 j의 작은 부분으로 수정되기를 원한다.
이것을 하기 위해서 너는 당므을 할 수 있다:
float mass_sum = A.mass + B.mass;
float ratio = A.mass / mass_sum;
A.velocity -= ratio * impulse;
ratio = B.mass / mass_sum;
B.velocity += ratio * impulse;
위의 코드가 이전의 ResolveCollision() 샘플 함수와 같다는 것을 깨다는 것이 중요하다. 이전에 명시되었듯이, inverse masses는 물리엔진에서 꽤 유용하다.
Sinking Objects
만약 우리가 아픙로가서, 이제까지 가진 코드를 사용한다면, 오브젝트들은 서로에게 가고, 튕겨 나갈 것이다. 이것은 훌륭하다. 만약 그 오브젝트들 중 하나가 무한의 질량을 가진다면 무엇이 발생하는가? 우리는 우리의 시뮬레이션에서 무한의 질랴을 나타내는 좋은 방법이 필요하다.
나는 infinite mass를 0으로 사용하는 것을 제안한다. 비록 만약 우리가 0을 가진 한 오브젝트의 inverse mass를 연산하려고 노력한다면, 우리는 zero로 나눌것이다. 이것을 하는 것은 inver semass를 연산할 때 다음의 것을 하는 것이다:
if(A.mass == 0)
A.inv_mass = 0
else
A.inv_mass = 1 / A.mass
0의 값은 impulse resolution동안 적절한 계산을 만들 것이다. 이것은 여전히 괜찮다. 어떤 것이 중력에 의해 다른 오브젝트에 가라앉기 시작했을 때 sinking objects의 문제가 발생한다. 아마도, low restitution을 가진 어떤 것이 무한의 질량을 가진 벽을 치고, 가라앉기 시작한다.
이 가라앉는 것은 floating point errors에 의한 것이다. 각 floating point calculation 동안, small floating point error가 하드웨어에 의해 도입된다 ( 더 많은 정보를 위해 Floating point error IEEE754를 구글링해라.) 시간이 흘러, 이 에러는 위치 에러로 축적이되고, 오브젝트들이 서로에게 가라앉게 한다.
이 에러를 고치기 위해서, 그것은 설명되어야 한다. 이 위치 에러를 고치기 위해서, 나는 linear projection이라고 불려지는 방법을 보여줄 것이다. Linear projection은 작은 퍼센트로 두 오브젝트들의 관통을 줄인다. 이것ㅇ은 impulse가 적용된 후에 수행된다. Positional correction은 매우 간단하다: 각 오브젝트를 collision normal n를 따라서 관통 깊이의 퍼센트 만큼 움직여라:
void PositionalCorrection(Object A, Object B)
{
const float percent = 0.2; // usually 20% to 80%
const float slop = 0.01; // usually 0.01 to 0.1
Vec2 correction = max(penetration - k_slop, 0.0f) / (A.inv_mass + B.inv_mass)) * percent * n;
A.position -= A.inv_mass * correction;
B.position += B.inv_mass * correction;
}
마지막 방정식 10의 버전에서, j가 왼쪽에 있고, 모든 것이 오른쪽에 있다. 이것은 우리가 impulse scalar j를 풀기 위해 몇 줄의 코드를 쓸 수 있다는 것을 의미한다.
위의 코드 샘플에서 주목해야할 몇 가지 것들이 있다. 첫 번쨰 것은 Line 10에서 체크이다. 이 체크는 매우 중요하다; 그것은 너가 objects가 서로를 향하고 있다면 collision을 해결하도록 한다.
만약 오브젝트들이 서로에게 멀어지고 있다면, 우리는 아무것도 하기를 원하지 않느다. 이것은 실제로 충돌하고 있다고 고려되지 않아야 할 오브젝트들이 서로에대해 resolving되는 것을 방지한다. 이것은 사람의 직관을 따르는 시뮬레이션을 만드는데 중요하다. 그 직관은 오브젝트 상호작용 동안 무엇이 발생하는가에 대한 것이다.
주목해야될 두 번째 것은, inverse mass가 이유없이 여러번 연산되는 것이다. 각 오브젝트 내에 inverse mass를 저장하여, 그것을 한 번 미리 연산하는 것이 가장 좋다:
많은 물리엔진들은 실제로 raw mass를 저장하지 않는다. 물리엔진은 종종 inverse mass * time 그리고 inverse mass를 홀로 저장한다. 그래서 질량과 관련된 대부분의 수학이 1/mass의 형태로 있다. 주목해야 할 마지막 것은 우리가 지능적으로 우리의 impulse scalar j를 두 오브젝트에 대해 분산하는 것이다. 우리는 작은 오브젝트들이 큰 오브젝트에 대해 큰 j의 부분으로 튕겨 나가기를 원하고, 큰 오브젝트들은 그것들의 속도가 j의 작은 부분으로 수정되기를 원한다.
이것을 하기 위해서 너는 당므을 할 수 있다:
float mass_sum = A.mass + B.mass;
float ratio = A.mass / mass_sum;
A.velocity -= ratio * impulse;
ratio = B.mass / mass_sum;
B.velocity += ratio * impulse;
위의 코드가 이전의 ResolveCollision() 샘플 함수와 같다는 것을 깨다는 것이 중요하다. 이전에 명시되었듯이, inverse masses는 물리엔진에서 꽤 유용하다.
Sinking Objects
만약 우리가 아픙로가서, 이제까지 가진 코드를 사용한다면, 오브젝트들은 서로에게 가고, 튕겨 나갈 것이다. 이것은 훌륭하다. 만약 그 오브젝트들 중 하나가 무한의 질량을 가진다면 무엇이 발생하는가? 우리는 우리의 시뮬레이션에서 무한의 질랴을 나타내는 좋은 방법이 필요하다.
나는 infinite mass를 0으로 사용하는 것을 제안한다. 비록 만약 우리가 0을 가진 한 오브젝트의 inverse mass를 연산하려고 노력한다면, 우리는 zero로 나눌것이다. 이것을 하는 것은 inver semass를 연산할 때 다음의 것을 하는 것이다:
if(A.mass == 0)
A.inv_mass = 0
else
A.inv_mass = 1 / A.mass
0의 값은 impulse resolution동안 적절한 계산을 만들 것이다. 이것은 여전히 괜찮다. 어떤 것이 중력에 의해 다른 오브젝트에 가라앉기 시작했을 때 sinking objects의 문제가 발생한다. 아마도, low restitution을 가진 어떤 것이 무한의 질량을 가진 벽을 치고, 가라앉기 시작한다.
이 가라앉는 것은 floating point errors에 의한 것이다. 각 floating point calculation 동안, small floating point error가 하드웨어에 의해 도입된다 ( 더 많은 정보를 위해 Floating point error IEEE754를 구글링해라.) 시간이 흘러, 이 에러는 위치 에러로 축적이되고, 오브젝트들이 서로에게 가라앉게 한다.
이 에러를 고치기 위해서, 그것은 설명되어야 한다. 이 위치 에러를 고치기 위해서, 나는 linear projection이라고 불려지는 방법을 보여줄 것이다. Linear projection은 작은 퍼센트로 두 오브젝트들의 관통을 줄인다. 이것ㅇ은 impulse가 적용된 후에 수행된다. Positional correction은 매우 간단하다: 각 오브젝트를 collision normal n를 따라서 관통 깊이의 퍼센트 만큼 움직여라:
void PositionalCorrection(Object A, Object B)
{
const float percent = 0.2; // usually 20% to 80%
const float slop = 0.01; // usually 0.01 to 0.1
Vec2 correction = max(penetration - k_slop, 0.0f) / (A.inv_mass + B.inv_mass)) * percent * n;
A.position -= A.inv_mass * correction;
B.position += B.inv_mass * correction;
}
이것은 오브젝트가 position correction이 kicking in 하는 것없이 관통하록 한다.
Simple Manifold Generation
이 자료에서 다룰 그 마지막 주제는 간단한 manifold generation이다. 수학 용어에서 manifold는 "공간에서 한 area를 나타내는 점들의 한 집합"의 대사이다. 그러나, 내가 manifold라는 용어를 언급할 때, 나는 두 오브젝트 사이의 충돌에 대한 정보를 포함하는 작은 오브젝트를 언급하고 있는 것이다.
여기에 일반적인 manifold setup이 있다:
struct Manifold
{
Object* A;
Object* B;
float penetration;
Vec2 normal;
};
Simple Manifold Generation
이 자료에서 다룰 그 마지막 주제는 간단한 manifold generation이다. 수학 용어에서 manifold는 "공간에서 한 area를 나타내는 점들의 한 집합"의 대사이다. 그러나, 내가 manifold라는 용어를 언급할 때, 나는 두 오브젝트 사이의 충돌에 대한 정보를 포함하는 작은 오브젝트를 언급하고 있는 것이다.
여기에 일반적인 manifold setup이 있다:
struct Manifold
{
Object* A;
Object* B;
float penetration;
Vec2 normal;
};
댓글 없음:
댓글 쓰기