Post Lists

2018년 9월 1일 토요일

3 The Laws of motions

The Laws of motions

물리엔진은 뉴턴의 운동 법칙을 기반으로 한다. 나중의 섹션에서, 우리는 뉴턴의 원래의 work에 추가된 결과를 사용하기 시작할 것이지만, 기본은 그의 것이다.

뉴턴은 세 개의 운동법칙을 만들었는데, 그것들은 한 point mass가 어떻게 행동하는지를 엄청난 정확성으로 묘사한다. point mass는 우리가 "particle"이라고 부르는것이지만, particle physics와 혼동되어진다. particle physics는 명백히 뉴턴의 법칙을 따르지 않는 전자 또는 광자같은 아주 작은 파티클들을 연구한다. 이 책에 대해서 우리는 point mass라기 보다는 particle을 사용할 것이다.

파티클을 넘어서, 우리는 회전의 물리학을 필요하다. 그것은 뉴턴의 법칙에 더해진 추가의 복잡함을 도입한다. 그러나 심지어 이러한 경우에, point-mass laws는 여전히 작동되어 보일 수 있다.

우리가 그 법칙을 보고, 그것들이 어떻게 구현되는지 보기 전에, 우리는 파티클이 우리의 엔진 안에서 무엇인지에 대해 볼 필요가 있고, 코드에서 어떻게 구성되는지 볼 필요 있다.

3.1 Particle
파티클은 위치를 가지지만, 방향은 없다. 다시 말해서, 우리는 파티클이 어떤 방향을 가리키고 있는 지에 대해서 구분하지 않는다: 그것은 중요하지 않거나 말이 되지 않는 둘 중 하나이다. 총알이 그 이전 카테고리이다: 한 게임에서, 우리는 총알이 어떤 방향을 가리키고 있는지를 정말 신경쓰지 않는다; 우리는 그것이 어떤 방향으로 움직이는지와 그것이 타겟에 부딪혔는지를 신경쓴다. 예를들어 폭발물로부터의 빛의 아주 작은 지점이 두 번째 카테고리이다: 빛의 빛의 한점이고, 빛의 한 spot이 어떤 방향을 가리키고 있는지를 묻는 것은 말이 되지 않는다.

각 particle에 대해, 우리는 다양한 특징들을 추적할 필요가 있다: 우리는 그것의 현재 위치, 그것의 속도, 그리고 그것의 가속도가 필요할 것이다. 우리는 우리가 진행함에 따라 파티클에 부가적인 특징을 추가할 것이다. 그 위치, 속도, 그리고 가속도는 모두 벡터이다.

그파티클은 다음의 구조로 구현되어질 수 있다:


class Particle
{
public:
 glm::vec3 m_position;
 glm::vec3 m_velocity;
 glm::vec3 m_acceleration;
};

이 구조를 사용하여, 우리는 우리의 첫 번째 물리엔진을 만들 몇 가지 기본 물리를 적용할수 있다.

3.2. The First Two Laws
뉴턴에 의해 사실로 상정된 세 가지 운동법칙이 있지만, 지금, 우리는 오직 처음 두 개만 필요할 것이다. 그것들은 한 오브젝트가 힘의 존재와 부재에서 행동하는 방식을 다룬다. 그 처음 두 개의 운동 법칙은 다음과 같다:


  1. 만약 한 힘이 그것에 작용하지 않는다면 한 오브젝트는 상수의 속도로 계속 나아간다.
  2. 한 오브젝트에 작용하는 한 힘은 오브젝트의 질량에 비례하는 가속도를 만들어낸다.


3.2.1 The First Law
첫 번째 법칙은 (Newton 1)은 우리에게 만약 주변에 힘이 없다면 무엇이 발생하는지를 말해준다. 그 오브젝트는 상수의 속도로 계속해서 움직일 것이다. 다시 말해서, 그 파티클의 속도는 결코 바뀌지 않을 것이다, 그리고 그것의 위치는 속도를 기반으로 계속 업데이트 될 것이다. 이것은 직과넞ㄱ이지 않을지도 모른다: 우리가 실 세계에서 움직이는 오브젝트들은 그것들이 끊임없이 힘을 받지 않는다면 느려질 것이고, 결국에는 멈출 것이다. 이 경우에 그 오브젝트는 한 힘을 계속 받고 있다 - force of drag(저항) (또는 마찰, 그것이 미끄러진다면) 실제 세계에서, 우리는 한 몸체에 작용하는 힘으로부터 벗어날 수 없다; 우리가 상상할 수있는 가장 가까운 것은 공간에서의 오브젝트의 움직임이다. 뉴턴의 1 법칙이 우리에게 말하는 것은 만약 우리가 모든 힘을 제거할 수 있다면, 그러면 오브젝트들은 같은 속도로 영원히 움직일 거라는 것이다.

우리의 물리엔진에서, 우리는  작용하는 힘이 없다고 간단히 가정할 수 있고 뉴턴 1법칙을 직접 사용할 수 있다. 저항을 재현하기 위해, 우리는 특별한 저항력을 추가할 수 있다. 이것은 우리가 책의 이부분에서 만드는 간단한 엔진에게 괜찮지만, 그것은 좀 더 복잡한 시스템과는 문제를 발생시킬 수 있다. 물리 계산을 수행하는 processor가 완전히 정확하지 않기 때문에 그 문제는 발생한다. 이 부정확성은 그것들 자신의 accord에 대해 더 빨라지는 오브젝트를 만들어 낸다.

더 좋은 솔루션은 drag의 rough approximation을 직접적으로 엔진에 통합하는 것이다. 이것은 우리가 오브젝트들이 numerical inaccuracy에 의해 가속되지 않도록 하고, 그것은 우리가 몇 가지 저항의 종류들을 재현하는 것을 허용한다. 만약 우리가 복잡한 drag를 필요하다면 (비행 시뮬레이터 또는 레이싱 게임에서 aerodynamic drag같은), 우리는 여전히 특별한 drag force를 만들어서 그것을 할 수 있다. 우리는 혼동을 피하기 위해서 drag의 간단한 형태를 "damping(제동)"이라고 부른다.

damping(제동)을 지원하기 위해서, 우리는 또 다른 특징을 그 파티클 클래스에 추가한다:

class Particle
{
public:
 glm::vec3 m_position;
 glm::vec3 m_velocity;
 glm::vec3 m_acceleration;

 real damping;
};

우리가 적분을 수행할 때, 우리는 각 업데이트할 때 그 오브젝트의 속도의 일정 비율을 제거할 것이다. 그 damping parameter는 속도가 업데이트 후에 얼마나 남을지를 조종한다. 만약 그 damping이 0이라면, 그 속도는 아무것도 남지 않을 것ㅇ디ㅏ. 이것은 그 오브젝트가 힘이 없어진 후에 어떠한 운동도 유지할 수 없다는 것을 의미한다. 그리고 그 플레이어에게는 이상하게 보일 것이다. 1의 값은 그 오브젝트가 그것의 모든 속도를 유지하는 것을 의미한다 (no damping가 동일하다). 만약 너가 그오브젝트가 drag를 겪고있느 ㄴ것처럼 보이지 않길 원한다면, 그러면 1에 근접한 값들이 최적이다 - 0.995. 예를들어.

3.2.2 The Second Law
두 번째 법칙(Newtown 2)는 우리에게 힘이 한 오브젝트의 움직임을 바꾼다는 메커니즘을 준다. 한 힘은 한 오브젝트의 가속도를 바꾸는 어떤 것이다 (즉, 속도의 변화율). 이 법칙이 의미하는 것은 우리가 한 오브젝트에게 그것의 위치나 속도롤 직접 바꾸기 위해 아무것도 할 수 없다는 것이다; 우리는 그 오브젝트가 우리의 타겟 위치 또는 속도에 도달할 때 까지 간접적으로 가속도를 바꾸기 위해 속도를 적용하고 기다리는 것을 할 수 있다. 우리는 나중에 그 책에서 물리 엔진이 좋게 보이기 위해 이 법칙을 남용하는 것을 볼 것이다. 그러나 지금은 건드리지 않을 것이다.

Newton 2법칙 때문에, 우리는 속도와 위치가 다른 파티클의 가속도를 다룰 것이다. 속도와 위치 둘 다 게임에서 프레임 마다의 양을 추적한다. 그것들은 변화하지만, 직접적으로 가속도에 의해 영향 받는다. 대조적으로 가속도는, 한 순간에서 다른 순간으로 갈 때 다를 수 있다. 우리는 우리가 맞다고 보도록 간단히 한 오브젝트의 가속도를 설정할 수 있다. 그리고 그 오브젝트의 행동은 괜찮아 보일 것이다. 만약 우리가 직접 그 속도나 위치를 설정한다면, 그 파티클은 갑자기 거칠게 움직이거나 튀어 오를 것이다. 이 것 때문에, 위치와 속도 특성은 적분기에 의해서 오직 변경되어질 것이고 직접 변경되어서는 안된다 (한 오브젝트의 초기 위치와 속도를 설정하는 것 외에는 물론). 가속도 특성은 언제든지 설정되어질 수 있고, 그것은 적분기에 의해서 남겨질 것이다.

3.2.3 The Force Equations
Newton 2의 두 번째 부분은 힘이 가속도와 어떻게 관련있는지를 말해준다. 같은 힘에 대해, 두 오브젝트들은 그것들의 질량에 따라 다른 가속도를 경험할 것이다. 힘과 가속도를 연관시키는 공식은 유형한

f = ma = m * doubledot(p)               [3.1]

이다.

여기에서 우리는 가속도를 찾는다. 우리는

doubledot(p) = 1/m * f                    [3.2]

여기에서 f는 힘이고, m는 질량이다.

물리엔진에서 우리는 일반적으로 서로에게 적용되는 힘들을 찾고, 가속도를 찾기 위해 방정식 3.2를 사용한다. 그리고 이것은 적분기에 의해 그 오브젝트에게 적용되어질 수 있다. 책의 이 부분에서 우리가 만들고 있는 엔진에 대해, 우리는 이 방정식을 사용하여 미리 가속도를 찾을 수 있다. 그것을 매 업데이트 마다 반복하지 않고. 책의 나머지에서 그러나, 그것을 중요한 단계가 될 것이다.

그래서 모든 방정식들이 그것들의 수학 교재 형태로 주어지고, 스칼라 값으로 적용된다. 우리가 지난 챕터에서 적분에 대해서 보았듯이, 우리는 그것들을 벡터를 사용하기 위해 쉽게 변환 시킬 수 있다.

그래서 힘은 벡터이고, 가속도 또한 그렇다.

3.2.4 Adding Mass to Particles
우리는 파티클마다 저장하는 위치와 속도에 더해서, 우리는 그것의 질량을 저장할 필요가 있다. 우리가 정확히 힘에 대한 그것의 반응을 계산할 수 있기 위해서 이다. 많은 물리엔진들은 간단히 각 오브젝트에 대해 스칼라 질량 값을 추가한다. 그러나 같은 효과를 얻기 위해 더 좋은 방법이 있다.

첫 째로, 방정식 3.2에 대해 유의해야 할 중요한 것이 있다. 만약 한 오브젝트의 질량이 0이라면, 그러면 그 가속도는 무한이 될 것이다. 그 힘이 0이 아닌 한, 이것은 발생해서는 안되는 상황이다 : 우리가 재현하는 어떠한 파티클도 0의 질량을 가져서는 안된다. 만약 우리가 zero mass particle을 재현하려고 한다면, 그것은 코드에서 divide-by-zero 에러를 만들 거싱다.

그러나, 무한의 질량을 재현하는 것을 종종 유용하다. 이러한 것들은 어떤 크기가 있는 힘이 움직일 수 없는 오브젝트이다. 그것들은 게임에서 움직일 수 없는 오브젝트들에게 유용하다: 예를들어, 벽 또는 바닥은 게임에서 움직일 수 없다. 만약 우리가 3.2에 무한의 질량을 준다면, 그러면 그 가속도는 우리가 기대하듯이 0이 될 것이다. 불행하게도, 대부분의 컴퓨터 언어에서 진정한 무한을 나타낼 수 없고, 모든 공통된 게임 프로세서에서 최적화된 수학 명령어는 무한을 처리하지 않는다. 우리는 다소 창의정이게 되어야 한다. 이상적으로 우리는 무한의 질량을 갖는 것은 쉽지만 zero masses를 얻는 것은 불가능한 솔루션을 원한다.

3.2의 방정식에서, 우리가 매번 1/mass를 사용한다는 것을 유의해라. 우리가 3.1의 방정식 형태를 쓰지 않을 것이기 때문에, 우리는 각 오브젝트에 대해 질량이 아닌 1/mass를 저장하여 우리의 계산을 가속화 시킬 수 있다. 우리는 이것을 "inverse mass"라고 부른다. 이것은 zero or infinite mass의 오브젝트를 표현하는 것에 대한 문제를 해결한다: 무한의 질량을 가진 오브젝트들은 zero inverse mass를 가지고, 이것은 설정하기에 쉽다. zero mass의 오브젝트들은 무한의 inverse mass를 가지고, 대부분의 프로그래밍 언어에서 명시되어질 수 없다.

우리는 우리의 파티클 클래스가 이 방식으로 inverse mass를 포함하도록 업데이트 한다:


class GPEDParticle
{
 glm::vec3 m_position;
 glm::vec3 m_velocity;
 glm::vec3 m_acceleration;

 real damping;
 real inverseMass;
};

너가 mass가 아닌 inverse mass를 다루고 있다고 기억하는 것이 중요하다. 기억하지 않고 파티클의 질량을 직접적으로 설정하는 것은 꽤 쉽다. 그리고 그것이 결국 완전히 스크린에서 부적절하게 행동하는 것을 보게 될 것이다 - 예를들어 아주 약하게 두드린 것으로도 움직이는 통이 밖으로 나가버린다.

이것을 돕기 위해, 나는 Particle class에서 inverseMass data field가 protected 되게 했다. inverse mass를 설정하기 위해, 너는 accessor function을 사용할 필요가 있다. 나는 setInverseMass와 setMass에 대한 함수를 제공한다. 대부분, 후자를 사용하는 것이 좀 더 편리하다. 만약 우리가 무한의 질량을 설정할 것이 아니라면.



3.2.5 Momentum and Velocity
비록 Newton 1이 종종 속도의 관점에서 소개될 지라도, 그것은 잘못 나타낸 것이다. 어떤 힘이 없이 상수인 것은 속도가 아니라, 운동량이다.

운동량은 속도와 질량의 곱이다. 질량이 일반적으로 상수이기 때문에, 우리는 그러므로 속도가 Newton 1에 의해 상수라고 가정할 수 있다. 한 이동하는 오브젝트가 질량을 바꾸는 사건에서, 그것의 속도 또한 변할 것이다. 심지어 힘이 없어도.

우리는 우리의 물리엔진에 대해 이것을 걱정할 필요가 없다. 왜냐하면 질량이 바뀌는 상황을 다루지 않을 것이기 때문이다. 그러나 우리가 나중에 회전에 대해 볼 때 중요한 구분이 될 것이다. 회전하는 오브젝트들은 그것들의 질량이 분산되는 방식을 바꿀 수 있기 때문이다. Newton 1의 회전 형태에서, 그것은 회전 속도의 변화를 의미한다. 어떠한 힘들이 작용하는 것 없이.

3.2.6 The Force of Gravity
중력의 힘은 물리엔진에서 가장 중요한 힘이다. 중력은 모든 오브젝트 쌍에게 적용된다: 그것들을 한 힘으로 끌어당기는 것은 그것들의 질량과 거리에 의존한다. Newton은 또한 이 사실을 발견하였고, 세 가지 운동 법칙에 따라, 행성과 달의 운동을 새로운 정확도의 수준으로 설명했다.

그가 우리에게 준 공식은 "만유인력의 법칙"이다:



여기에서 m1과 m2는 두 오브젝트들의 질량이고, r은 그것들 중심 사이의 거리이고, f는 결과 힘이다. G는 "만유 인력 상수"이다 - 행성의 움직임의 관찰로부터 유도된 scaling factor이다.

두 오브젝트 사이의 중력의 효과인 한 행성의 크기는 중요하다; 차, 심지어 빌딩 같은 (상대적으로) 작은 오브젝트들 사이의 효과는 작다. 지구에서, 중력에 대한 우리의 경험은 완전히 지구 그 자체에 의해 지배된다. 우리는 우리의 조수가 작동하는 방식에서 달이 당기는 것을 눈치챈다. 우리가 오직 중력이 우리를 행성의 표면으로 끌어당기는 것 외에도.

우리는 오직 지구가 끌어 당기는 것에만 관심이 있기 때문에, 우리는 방정식 3.3을 간단하게 할 수 있다. 처음에 우리는 m_1이 항상 상수라고 가정할 수 있다. 둘 째로, 덜 명백하게, 우리는 r 또한 상수라고 ㄱ자ㅓㅇ할 수 있다. 이것은 포함된 큰 거리 때문이다. 지구의 표면에서 그것의 중심까지의 거리는 엄청 크다 (6,400 km) 그래서 해수면에서 서있는 것의 중력과 산 꼭대기에서 서있는 것 사이에 거의 차이가 없다. 우리가 게임에서 필요한 정확성을 위해, 우리는 그러므로 r parameter를 상수로 가정할 수 있다.

방정식 3.3은 다음으로 간단하게 된다



여기에서 m은 우리가 재현하는 오브젝트의 질량이다; 이전처럼 f는 힘이다. 그리고 g는 만유인력 상수, 지구 질량, 그리고 그것의 반경을 포함하는 상수이다:



그 상수 g는 한 가속도이고, 우리가 m/s^2으로 측정한다. 지구에서 이 g 상수는 약 10m/s^2의 값으 ㄹ가진다 (과학자들은 가끔식 9.807 m/s^2의 값을 사용한다. 비록 r의 변화와 다른 효과 때문에, 이것이 측정된 값보다 global average이지만).

힘이 오브젝트의 질량에 의존한다는 것에 유의해라. 만약 우리가 방정식 3.2를 사용하여 가속도를 처리한다면, 그러면 우리는 다음을 얻는다



다시 말해서, 그 오브젝트의 질량이 무엇이든지, 그것은 항상 중력 때문에 같은 비율로 가속할 것이다. 전설대로, 갈릴레오는 무겁고 가벼운 물체들을 피사의 사탑으로부터 떨어 뜨렸고, 그것들이 땅에 동시에 떨어졌다는 것을 보여줬었다.

이것이 우리 엔진에 대해 의미하는 것은 우리가 적용할 필요가 있는 가장 중요한 힘은 직접적으로 가속도에 적용되어질 수 있다는 것이다. 힘을 계산하기 위해 방정식 3.4를 사용하고, 그것을 다시 가속도로 변환하기 위해 방정식 3.2를 사용하는 시점은 없다. 이 엔진의 iteration에서, 우리는 중력을 파티클에 작용하는 단일의 힘으로 도입할 것이다. 그리고 그것은 직접 가속도로서 적용될 것이다.

The Value of G
지구에서 중력 때문에 가속도가 10m/s^2일지라도, 이것이 스크린에서는 매우 그럴듯해 보이지 않다라는 것을 주목할 가치가 있다. 게임은 좀 더 실제 세계보다 흥분되려는 경향이 있다: 상황은 좀 더 빠르게 발생하고 더 높은 강도로 발생한다.

10m/s^2의 g의 값으로 시뮬레이션을 만드는 것은 무뎌보이고, 재미없어 보일 수 있다. 대부분의 개발자들은 더 높은 값을 쓴다. 약 15m/s^2으로.  슈터들에게는 20m/s^2까지 (땅으로 너무 빠르게 가속되는 발사체를 피하기 위해), 그리고 이것은 일반적으로 게임을 진행시키는 것이다. 몇몇 개발자는 더 가기도 하고, 오브젝트마다 기반으로 g value를 조정하는 기술을 넣기도 한다. 우리의 엔진은 이 기능을 포함할 것이다.

중력은 일반적으로 아래 방향으로 작용한다. 만약 너가 특별한 효과를 쓰지 않는다면. 대부분의 게임에서, Y축은 게임 세계에서 위 아래를 나타낸다; 그리고 거의 배타적으로 양의 Y축은 위를 가리킨다.

중력 때문에 가속도는 그러므로 벡터로서 다음의 형태를 가진 벡터로 나타낼 수 있다



g가 우리가 이전에 이야기 한 값이고, 다음 섹션에서 파티클을 업데이트하기 위해 우리가 사용할 g는 가속도 벡터이다.

3.3 The Integrator
우리는 이제 엔진의 그 첫 번째 구현을 끝내는데 필요한 배경지식과 모든 방정식을 가졌다. 각 프레임마다, 그 엔진은 각 오브젝트를 차례로 볼 필요가 있고, 그것의 가속도를 처리하고, 적분 단계를 수행한다. 이 경우에 가속도의 계산은 사소할 것이다: 우리는 오직 중력 때문에 가속도를 사용할 것이다.

적분기는 두 부분으로 구성된다 : 그 오브젝트의 위치를 업데이트 시킬 것과, 속도를 업데이트 시키는 다른 것. 그 위치는 속도와 가속도에 의존할 것이다. 반면에 속도는 오직 가속도에만 의존할 것이다.

적분은 위치와 속도를 업데이트하기 위해 시간간격을 요구한다: 우리가 매 프레임마다 업데이트하기 때문에, 우리는 프레임 마다의 시간 간격을 업데이트 시간으로서 사용한다. 만약 너의 엔진이 일관된 프레임율을 가지는 콘솔에서 작동한다면, 그러면 너는 이 값을 너의 코드에 하드코딩할 수 있다 (비록 그렇게 하지 않는 것이 현명할지라도, 같은 콘솔에서 다른 환경은 다른 프레임율을 가질 수 있기 때문에). 만약 너가 다양한 프레임율을 가진 PC에서 작동한다면, 그러면 너는 아마도 프레임의 duration을 체크할 필요가 있다.

일반적으로 개발잗르은 한 프레임 시간을 체크하고, 그러고나서 그 다음 프레임을 업데이트하기위해 그 값을 사용한다. 만약 frame durations이 극적으로 비일관되게 된다면 이것은 눈에 띌만한 jolt를 만들 수 있다. 그러나 그 게임은 이 경우에 어쨌든 부드럽게 느껴지지 않을 가능성이 높다. 그래서 그것은 경험의 법칙이다.

코드에서, 나는 매 프레임의 duration을 계산하는 central timing system을 사용한다. 우리가 여기에서 개발할 그 물리 코드는 그것이 업데이트 될 때 time parameter를 취하고, 이 값이 어떻게 계산되었는지를 신경쓰지 않는다.

3.3.1 The Update Equations
우리는 위치와 속도 둘 다 업데이트 시킬 필요가 있다; 각각은 다소 다르게 다뤄진다.

Position Update
chapter 2에서, 우리는 가속도를 두 번 적분하는 것은 우리에게 위치 업데이트에 대한 이 방정식을 준다:

p' = p + dot(p)t + 1/2 ddot(p)t^2

이것은 고등학교와 대학생 수학 교재에서 보이는 잘알려진 방정식이다.

우리는 엔진에서 position update를 수행하기 위해 이 방정식을 사용할 수 있다. 이것과 같은 코드로

object.position += object.velocity * time + object.acceleration * time * time * 0.5;

사실, 만약 우리가 매 프레임마다 업데이트 한다면, 그 시간 간격은 매우 작을 것이다 (일반적으로 30 frame 게임에서 0.033). 만약 우리가 이 방정식의 가속도 부분을 본다면, 우리는 제곱 시간의 절반을 취한다 (이것은 0.0005를 준다). 이것은 너무 작은 값이여서, 그 가속도가 한 오브젝트의 위치 변화에 영향을 줄 가능성이 높지 않다.

이 이유 때문에, 우리는 일반적으로 위치 업데이트에서 전적으로 가속도를 무시하고, 더 간단한 형태를 사용한다

p' = p + dot(p)t

이것은 우리가 이 책 전반에서 적분기에서 사용할 방정식이다.

만약 너의 게임이 일반적으로 큰 가속도의 short bursts를 사용한다면, 그러면 너는 방정식의 더 긴 혀앹를 쓰는게 낫다. 만약 너가 큰 가속도를 사용하려고 한다면, 그러나, 너는 모든 종류의 다른 정확성 문제를 갖게 될 가능성이 높다: 모든 물리엔진은 일반적으로 매우 큰 가속도와는 불안정하다.

Velocity Update
속도 업데이트는 비슷한 기본 폼을 갖는다

dot(p)' = dot(p) + ddot(p)t

그러나 그 챕터 초반에, 우리는 속도를 변경하는 또 다른 요소를 도입했었다: damping parameter

그 damping parameter는 각 프레임에서 속도를 조금 줄이기 위해 사용된다. 이것은 간단히 속도에 damping factor를 곱해서 처리된다



여기에서 d는 그 오브젝트에 대한 damping이다.

그러나 이 방정식의 형태는 한 문제를 숨긴다. 우리가 업데이트 할 길거나 짧은 시간 간격을 가지든 말든, 제거되는 속도의 양은 같다. 만약 우리의 프레임율이 갑자기 상승한다면, 그러면 초당 더 많은 업데이트가 있을 것이고, 그 오브젝트는 갑자기 좀 더 많은 저항을 갖는 것처럼 보일 것이다. 그 방정식의 좀 더 옳은 버전은 이 문제를 그 방정식의 drag part에 시간을 넣어서 해결하는 것이다:



여기에서 damping parameter d는 매프레임이아닌 이제 매초마다 보유되는 속도에 비례이다.

다른것의 지수승으로 한 floating-point number를 계산하는 것은 대부분의 현대 하드웨어에서 느린 프로세스이다. 만약 너가 많은 오브젝트를 재현한다면, 그러면 일반적으로 이 단계를 피하는 것이 가장 좋다. 예를들어 수천개의 스파크들을 재현하도록 설계된 파티클 물리엔진에 대해, 방정식 3.5를 사용해라. 또는 심지어 damping을 제거해라.

우리가 더 작은 개수의 rigid bodies를 재현하기 위해 설계된 한 엔진을 향하고 있기 때문에, 나는 방정식 3.6에서 주어지듯이 이 책의 full form을 사용할 것이다. 많은 엔진 개발자들에 의해 선호되는 다른 접근법은 방정식 3.5를 1에 가까운 damping value로 사용하는 것이다 - 이것은 너무 작아서, 그래서 그것이 플레이어들에게 눈치챌만하지 않고, numerical instability problem을 해결할 수 있기에 충분히 크다. 이 경우에, 프레임율의 변화는 어떠한 시각적 차이를 만들지 않을 것이다. Drag forces는 그러고나서 만들어질 수 있고, 각 오브젝트에 작용하는 explicit forces로 적용되어질 수 있다 (chapter 5에서 보게 될 것이다).

불행하게도, 이것은 간단히 코드의 다른 부분으로 문제를 옮긴다 - 우리가 drag force의 사이즈를 계산하는 부분. 이 이유 때문에, 나는 damping parameter가 좀 더 유연하게 만드는 것을 선호하고, 그것이 시각적 수준의 drag를 재현하기위해 사용되는 것을 허용한다.

3.3.2 The Complete Integrator
우리는 이제 우리의 integrator unit을 구현할 수 있다. 코드는 이것처럼 보인다:


void GPEDParticle::integrate(real duration)
{
 assert(duration > 0.0);

 // Update linear position
 m_position += m_velocity * duration;

 // Work out the acceleration from the force
 glm::vec3 resultingAcc = m_acceleration;
 resultingAcc += m_forceAccum * inverseMass;

 // Update linear velocity from the acceleration
 m_velocity += resultingAcc * duration;

 // Impose drag
 m_velocity *= real_pow(damping, duration);
}

나는 Particle class에 integration method를 추가했다. 왜냐하면 그것은 간단히 파티클의 내부 데이터를 업데이트 시키기 때문이다. 그것은 time interval를 취하고, 파티클의 위치와 속도를 업데이트 시킨다. 그리고 어떠한 데이터도 반환하지 않는다.

3.4 Summary
두 개의 짧은 챕터에서, 우리는 벡터를 다루는 것부터 처음으로 완전하 물리엔진까지 갔다.

움직임의 법칙은 우아하고, 간단하며, 믿을 수 없도록 강력하다. 뉴턴이 발견했던 그 기초가되는 연결들은 이 책에서 모든 물리 시뮬레이션을 주도한다. 힘을 계산하고, 힘을 기반으로 위치와 속도를 적분하는 것, 힘과 시간을 기반으로 위치와 속도를 적분하는 것은 복잡하거나 간단한 모든 물리 엔진들의 기본 단계뜰이다.

비록 우리가 이제 실제로 게임들에서 사용되어질 수 있는 물리엔진을 가질지라도 (수 백개의 출시된 게임들에서 사용된 시스템과 동일한), 그것은 아직 물리 프로그램의 넓은 범위에 대해 적절하지 않다. chapter 4에서, 우리는 그것을 지지해줄 수 있는 프로그램 몇 개를 볼 것이고, 그것의 제한들을 볼 것이다.











댓글 없음:

댓글 쓰기