2015년 5월 4일 월요일

[일기] 기분나쁜 일기장 Springs and Springlike Things (6.3.2 ~ )

 6.3.2 Faking Stiff Springs

   이번 절에서 고강도 스프링을 지원하기 위해 다른 스프링힘을 계산하는 방식을 사용하는 좀더 개선된 형태의 스프링 힘 발생기를 구현할 것이다. 약간의 소위 '치트'를 고강도 스프링이 동작하게 하도록 하기 위해 사용한다. 이 책의 나머지 장에서 접촉과 충돌 그리고 제약들을 시연하기 위한 견고한 기술을 살펴보게 된다.

  이 절은 생략해도 무관하다. 수학적으로도 깊게 탐구하지 않을 뿐더러, 거짓된 고강도 스프링을 사용하는 곳에는 제약이 많아서 소개되는 공식들이 항상 동작하리라는 보장은 할 수 없기 때문이다. 특히, 각각의 눈속임으로 만든 고강도 스프링의 시연은 각각이 적절한 정도의 효과를 모사할 수 있지만, 하나 이상의 스프링들이 연결되거나 일련의 물체들이 이러한 용수철에 연결되어 있다면 계산으로부터 증가하는 부정확한 물리적 값들은 지저분하게 상호작용할 것이고 몇 문제들을 일으킬 것이다. 올바른(타당한) 상황이라면 힘 발생기 라이브러리에 이 구현이 포함해도 된다. (????)

  우리는 시간 간격이 지남에 따라 힘이 어떻게 변해가는지를 예측하거나 평균 힘을 생성하는 방법을 통해 이 문제를 어느 정도는 해결할 수 있다. 이 방법은 종종 '암시적 용수철(?;implicit spring)'이라고 하며, 이 방식으로 변화하는 힘을 다룰 수 있는 물리 엔진을 암시적이다 또는 반(半)-암시적이라고 한다...(?). 이러한 이유로 본 장의 마지막에서 우리는 fake the correct behavior 이상의 것은 할 수 없음을 볼 것이다. 따라서 나는 이 접근을 'fake implicit force generation'이라 부른다. (좌절하겠다, 못 알아듣겠어 ㅠㅜ)

 힘의 수식을 계산하기 위해 용수철이 그 자체로 남겨졌을 때 어떻게 행동하게 될지를 이해할 필요가 있다.

  Harmonic Motion (조화 운동)

  용수철은 마찰이나 저항이 없는 곳에서 영원히 진동한다. 스프링을 어느 정도 잡아당긴 후에 그것을 놓으면, 용수철의 양끝은 서로를 향해 가속된다. 그리고 평형 길이를 지나가고 압축되기 시작한다. 다시 초기에 확장한 정도와 같은 수준으로 정확하게 양끝이 압축했다면, 양끝은 서로의 반대 방향으로 가속되기 시작한다. 이 과정이 무한하게 순환된다. 이러한 운동의 종류는 물리학자들에게 잘 알려져 있으며 소위 단순 조화 운동(simple harmonic motion)이라 불린다. 용수철의 한 끝의 위치는 다음 수식을 따른다.

[식 6.3]

 여기서 k는 스프링 상수를 뜻하며, m 은 물체의 질량, X는 수식을 간편하게 표현하기 위해 다음과 같이 정의된 상수이다.

[x 식]


 식 [6.3]의 종류는 미분 방정식(differential equation)이라 불린다. 식에는 서로 다른 미분계수를 갖는 도함수들의 관계가 나타난다. 때때로 원시함수를 포함한다. 여기서는 이계도함수 dp2와 원시함수 p가 나타났다. 미분 방정식은 원시함수에 대한 식을 제공함으로 풀어낼 수 있다. 위의 주어진 식의 경우, 현재 시간에 따른 위치의 관계를 연결함으로써 방정식을 풀 수 있다. 그 해는 다음과 같다.

[식 6.4]


 여기서 p0는 예측의 시작시점에서의 평형 길이에 상대적인, 용수철 한 끝의 위치이며, dp0는 그 시점에서의 속도이다.

  여기서 식 [6.4]의 t를 우리가 관심 있는 시간 간격에서의 결과로 대입하고 식을 계산한다면, 용수철이 그 본연 그대로 놓여졌을 때, 특정 시간에 대해 용수철의 끝이 어디에 위치하게 될지를 알아낼 수 있게 된다. 그리고, 한 프레임의 기간동안 물체를 정확한 위치로 보정시키기 위해(이동시키기 위해) 적용할 충분한 큰 힘을 제공할 수 있다. 만일 최종 위치가 pt로 주어진다면, 그곳까지 도달하기 위한 힘은 다음과 같이 될 것이며,

[식  f=ma]


 그러면 가속도 dp2는 다음과 같이 주어진다.

[식 6.5]


 비록 이 식이 입자를 정확한 위치로 위치시킨다고 하더라도 그 위치에서의 정확한 속도까지 보장하는 것은 아니다. 이번 섹션의 마지막 부분에서 이 실패로 인해 초래되는 문제를 다시 논할 것이다.

Damped Harmonic Motion ( 감쇠 진동 )

  현실의 실제 용수철은 스프링힘에 따른 저항을 받는다. 용수철은 같은 위치로 영원히 진동하지 않을 것이고, 최대 진폭은 점차 시간에 따라 줄어들어 용수철의 끝은 평형 위치에서 멈추게 될 것이다. 이러한 점진적인 감소는 스프링이 겪는 저항에 의해 유발된다.

  만약 우리의 엔진을 보통때와 같이 구동시키는 경우, 저항은 damping parameter에 의해 구현됨을 알게 될 것이다. 우리가 이전의 공식에 따라 스프링의 움직임을 예측할 때에는 이러한 감쇠는 전혀 고려되지 않았다.

  우리는 따라서 식에 이를 고려하도록 감쇠 파라미터를 수식에 추가할 수 있다. 미분방적식 [6.3]은 다음과 같이 변할 것이며

[식 댐팽]


각 변수의 의미는 유사하다.  k는 용수철 상수이며(여기서는 X가 없다) d는 감쇠율이다(이전 장의 식 [5.1]의 k1에 상응한다).  이 등식에 따르면 drag(저항)은 속도 제곱에 비례하지 않는다. - 즉, 식 [5.1]의 k2 값과 같지 않다. - 우리가 이를 비례하도록 추가하기 위해 식을 변경한다면 최종의 식을 이해하기 위해 요구되는 수학개념은 상당히 난해하고 식 또한 복잡하다. 딱히 눈에 띄는 전진이 없는데도 말이다(우리는 꼼수에 집중을 하고 있다). 따라서 저항의 가장 간결한 상태를 고집해 나가기로 한다.

  상위의 미분 방정식을 푸는 것은 미래의 시간에 대한 위치 표현식을 얻는 것으로부터 가능하다. 즉,

[미방 해]


이 되며, R은 다음과 같이 주어진 상수이다.

[r 상수]


그리고 c는 다음과 같이 주어진 상수벡터이다.

[c 벡터]


  식에서의 t에 시간 간격을 대입함으로써, 우리는 pt의 값을 얻을 수 있으며, 식 [6.5]에 따라 요구되는 가속력을 계산할 수 있다. 정규 조화 운동에서와 같은 방식으로 말이다.

 Implementation


  암묵적 용수철힘 발생기를 구현할 코드는 다음과 같이 생겼다.

- precision.h 발췌 -
----------------------------------------------------------------------------------------
#define real_sin sinf ///사인 함수 재정의
#define real_cos cosf ///코사인 함수 재정의
#define real_exp expf ///지수함수 재정의
----------------------------------------------------------------------------------------
- pfgen.h 발췌 -
----------------------------------------------------------------------------------------
/**
* @details 고강도 스프링을 모사하는 흉내내기용 힘 발생기. 여기서 한 끝은 공간의 한 점에 고정되어 있다.
*/
class ParticleFakeSpring : public ParticleForceGenerator {
/** 고정점 위치 */
Vector3* anchor;

/** 스프링 상수 */
real springConstant;

/** 스프링 진동 감쇠률 */
real damping;

public:

//파라미터 형태의 생성자
ParticleFakeSpring(Vector3* anchor, real springConstant, real damping);

/** 대상 입자에 힘 적용하기 */
virtual void updateForce(Particle* particle, real duration);
};
----------------------------------------------------------------------------------------
- pfgen.cpp 발췌 -
----------------------------------------------------------------------------------------
void ParticleFakeSpring::updateForce(Particle* particle, real duration) {
// 무한의 질량은 무시한다.
if (!particle->hasFiniteMass()) return;

// 고정점에 대한 입자의 상대적 위치를 계산한다.
Vector3 position;
particle->getPosition(&position);
position -= *anchor;

// 값들이 정의역 내에 있는지 아닌지를 학인하고 상수값들을 계산한다.
real gamma = 0.5f * real_sqrt(4 * springConstant - damping * damping);
if (gamma == 0.0f) return;
Vector3 c = position * (damping / (2.0f * gamma)) + particle->getVelocity() * (1.0f / gamma);

// 타겟 위치를 계산한다. 미분방적식의 해를 적용
Vector3 target = position * real_cos(gamma * duration) + c * real_sin(gamma * duration);
target *= real_exp(-0.5f * duration * damping);

//힘과 가속도를 계산한다.
Vector3 accel = (target - position) * (1.0f / duration*duration) - particle->getVelocity() * duration;
particle->addForce(accel * particle->getMass());

//상위는 수식으로부터 그대로 도출됨.
}
----------------------------------------------------------------------------------------

 이 힘 발생기는 전에 만들었던 고정된 스프링 힘 발생기와 유사한 구조를 가진다. 단 하나의 두드러지는 차이가 있다면 여기서 구성된 용수철은 그 본연의 평형 길이를 가지고 있지 않다는 점이다. 이 사실과 (두 물체를 끌어당기는 , 양 끝이 자유로운 스프링 대신) 한 끝이 고정된 용수철을 사용한 사실은 이곳에서 계산을 용이하게 하기 위함이다(제한점을 두었다). 결론을 말하자면, 항상 길의 0의 평형 길이를 가져야 한다는 제약을 걸었다.

 Zero Rest Lengths ( 평형 길이 0 ;???)

  만약 용수철이 평형 길이가 0이라고 한다면, 용수철에 생긴 어떠한 변위는 반드시 확장으로 간주된다. 만약 우리가 용수철의 한 끝을 고정시킨다면 반드시 용수철에 작용하는 복원력은 고정점을 향하는 방향으로 생기게 된다.

  용수철의 양 끝이 자유로이 움직일 수 있는 경우에는 힘의 방향을 결정짓는 것이 무척이나 어려워진다. 이전의 공식들은 힘이 물체의 위치에 대해서만 정리되었다. 만약 우리가 용수철을 고정시키지 않는다면 우리는 등식에 용수철의 다른 한 끝의 물체의 운동을 포함시켜야만 하는데 이렇게 될 경우, 식의 해를 구할 수 없게 된다. (서로 의존적이므로)

  용수철의 한 끝은 고정했으나 0이 아닌 평형 길이를 갖는 용수철을 사용할 때에도 같은 문제가 발생한다. 일차원 관점에서 0이 아닌 평형 길이의 경우는, 평형점이 단지 다른 곳으로 이동한 것으로 간주될 수 있다. 그런데 3차원으로 확장될 경우 용수철은 빙빙 돌수 있게 되며 이 때는 이 기준 평형 위치가 궤도를 타고 움직일 수 있음을 의미한다. 따라서 힘의 방향을 결정짓는 과정과 특정 평형점 위치에 따른 물체의 운동을 식을 통해 기술하는(알아내는) 것은 어려워진다. -- 드디어 이해한 것 같다. 그런데 말로 못 쓰겠다... ㅠㅠ



 Velocity Mismatches ( 속도 부조화 )

  지금까지 우리는 위치에 대해서만 논의했다. 식 [6.5]는 물체를 예측된 위치로 위치시키기 위한 힘을 얻을 수 있다. 불행하게도, 물체는 해당 위치에 도달했을 때, 정확한 속도를 갖지 않는다(비록 참값에 근접한다). 과연 물체의 속도는 점점 증가하여 매 시간마다 빨라지고 결국 무한으로 치닫게 될까? (앞에 언급한 문제 상황에서 속도는 증가했었다)

  감쇠 진동 운동에서 고정점이 움직이지 않을 때는 위와 같은 예측을 수행한 결과로 나타나는 속도는 절대로 무한을 만족시킬 만큼 증가하지 않는다. 이를 증명하는데 수반되는 수학은 매우 복잡하므로, 증명은 회의론자들에게 숙제로 남기도록 하겠다.

  비록 우리는 폭발적인 속도를 경험하지 않는다 하더라도, 결과적으로 얻게 되는 속도와 정확한 속도 간의 부조화는 용수철이 마치 일관적이지 않는 용수철 상수를 갖는 것처럼 행동하는 것처럼 보이게 한다. 용수철이 가끔 우리가 명시한 것보다도 더 고강도를 갖는 것처럼 보여질 수 있으며, 또는 더 강도가 낮을 수도 있다. 대부분에 경우에 있어서 이러한 사항은 크게 눈에 띄지는 않는다. 그러나 이는 우리가 만든 힘을 꾸며내는 방식의 무시못할 결과임을 알아야 한다.

Interacting with Other Forces

  또다른 거짓 스프링 힘 발생기의 주된 한계는 이 힘이 다른 힘들과 상호작용하는 방식이다.

  이전의 수식들은 물체가 자유롭게 움직임을 전제로 하였고 또한 물체들이 다른 어떠한 힘의 영향을 받지 않는다는 전제도 깔려 있다. 스프링힘은 시간 간격이 지남에 따라 감소하게 되고 이는 용수철이 자신의 평형 위치를 향해 움직이고 있기 때문이다. 만약 우리가 용수철을 일정한 길이로 압축하거나 늘어뜨리는 또 다른 힘을 추가한다면 이제 용수철힘은 일정해질 것이다. 그리고 기존의 본연의 힘 발생기는 완벽한(완전한) 결과를 줄 것이다. 스프링 상수는 더 이상 문제가 되지 않는다.

  우리는 이론적으로 모든 다른 힘들을 통합하여 한 스프링 힘 발생기 안에 둘 수 있다. 그렇게 되면 힘 발생기는 정확하게 올바른 힘을 돌려줄 것이다. 그러나 불행하게도, 그 힘을 정확하게 알아내기 위해서는 우리는 시연되는 모든 물체들의 행동을 알아야 할지도 모른다. 모든 물체들의 행동을 시연하는 것은 물론, 전체적인 물리 엔진의 목적이다. 따라서 이를 가능하게 할 수 있는 유일한 방법은 힘 계산을 할 때 완전한 물리 엔진의 도움을 받는 것이다. 이러한 관행은 없다(사실, 엄격히 말해서 이는 불가능한데 물리 엔진을 만들 때 완전한 물리 엔진이 필요하다면 물리 엔진을 만들 수 있는 방법이 없기 때문이다).

  늘어난 채로 유지되도록 의도된 용수철에 대해서는(밧줄 다리를 지탱하는 용수철과 같은), 흉내내어진(??) 용수철힘은 너무나 작을 것인데 그게 대부분 상당히 작을 것이다. 관행적으로 당신이 원하는 효과를 얻기 위해 기술의 혼합을 찾는 시도는 최고의 작업이다. 여기선 게임에서 다른 물체들을 위한 서로 다른 용수철 힘 발생기를 사용함으로써 기술의 혼합을 찾는다.(???)

  저자는 캐릭터의 머리카락을 흉내기반(?거짓) 힘 발생기(?; faked force generator)를 사용하여 스프링으로 모델링 하는 작업을 성공적으로 마친 기억이 있다. 평형 위치는 3D 모델의 머리카락 버텍스의 본위치로 잡았으며 스프링힘은 실제로 화면에 그려진 버텍스를 이 평형 위치로 끌어당겼다. 캐릭터가 움직임에 따라, 그녀의 머리카락은 좌우로 자연스럽게 움직였다. 이 방법은 이상적으로 위에서 겪은 문제에 적합하다. 왜냐하면 정점(버텍스)들은 어느 경우에서도 다른 힘은 받지 않는다(중력에 의해 나타나는 자연스러운 머리카락의 낙하는 모델 디자인의 아티스트에 의해 구현된 것이다). 그리고 그들은 너무 튕기듯이 보이지 않기 위해서 스프링 계수가 매우 높게 설정되어야 할 필요가 있었다. 이 머리탄성에 대한 CD 내의 예제는 이 동작에 대한 간단한 예시가 포함되어 있다.

6.4 Summary ( 요약 )

  정말 놀라우리만큼 많은 수의 물리 현상이 훅의 법칙을 통해서 모델링 될수 있다. 몇몇의, 가령 부력과 같은 효과들은 같은 코드를 사용해서 지원되는 용수철이 가진 것과 같은 유사한 속성들을 가지고 있다.

  우리는 힘 발생기의 한 집합을 구축했는데 이 책의 나머지 부분에 걸쳐서 부양성이 있거나 탄성이 나타나는 모든 물체들을 모델링하는데 사용될 것이다. 그러나 또한 책의 나머지 전반에서 동기를 유발하는 문제의 시작도 함께 보아왔다. 이 문제는 높은 스프링 상수를 가진 용수철은 프레임-프레임 기반의 기초에서 시연하기가 무척 어렵다는 내용을 포함한다. 스프링의 행동이 시연되는 프레임 사이의 시간 간격보다 빠르다면 용수철은 제멋대로 행동하고 제어가 불가능해지게 될 수 있다.

  만약 이러한 문제가 없다면, 우리는 우리는 용수철 같은 힘들을 이용하여 거의 모든 물체를 시연할 수 있었을 수도 있다. 모든 충돌은, 예를 들어, 쉽게 다뤄질 수도 있다. 비록 우리가 몇 가지 경우에서 고강도 스프링을 흉내내는 것만이 가능하다 하더라도, 이 해결책은 일반적인 경우에 있어서 고강도 용수철의 문제를 극복할 만큼 튼튼하지 않다. 따라서 우리가 필요한 것은 대안적인 접근이며 충돌의 매우 빠른 튐을 다루기 위함이다. 7장에서는 이를 살펴볼 것이다. - 충돌을 다루고 장대와 비탄성 케이블과 같은 경중 제한을 다루기 위해 특별한 경우의 코드 집합을 구축할 것이다.

 쓰고도 무슨 소린지 모르겠다.. 영어 공부해야겠다..

댓글 없음:

댓글 쓰기