Post Lists

2018년 9월 8일 토요일

8 The Mass-AggreGate Physics Engine

8 The Mass-Aggregate Physics Engine
우리는 파티클 시뮬레이션과 rods, cables, and springs로 연결된 많은 오브젝트들로 만들어진 구조물 둘 다 가능한 이제 mass-aggregate physics engine 구성해왔다. 몇 가지 예제 시나리오들로 엔진을 테스트 할 시간이다.

그러나 그 엔진은 여전히 한계를 가지고 있다; 특히, 오브젝트들이 회전하는 방법을 묘사할 수 없다. 우리는 이것과 관련한 방법들을 볼 것이다. 그리고 mass aggregates의 관점에서 오브젝트들의 회전을 fake할 것이다. 그것은 몇 몇 프로그램들에 대해 유용한 테크닉이고, 좀 더 고급 물리학에 대한 필요성을 제거할 수 있다.

8.1 Overview of the Engine
그 mass-aggregate physics engine은 세 가지 요소들을 갖는다:

  1. 그 파티클들 그 자체는 그것들의 위치, 움직임, 질량을 추적한다. 시뮬레이션을 준비하기 위해,우리는 무슨 파티클들이 필요한지를 처리할 필요가 있고, 그것들의 초기 위치 속도를 설정할 필요가 있다. 우리는 또한 그것들의 inverse mass를 설정할 필요가 있다. 한 오브젝트의 중력가속도는 또한 rigid body에서 유지된다 (이것은 너가 바란다면, force에 의해 제거되고 대체될 수 있다).
  2. force generators가 게임의 몇 가지 프레임들 동안 적용되는 힘들을 추적하기 위해 사용된다.
  3. collision system은 contact objects의 한 집합을 축적하고, 그것들을 contact solver에 넘긴다. 어떤 코드는 새로운 contacts를 생성할 수 있다. 우리는 두 가지를 고려해온다 : collision  detector and rod or cable constraints.
매 프레임에서, 우리는 각 파티클을 취하고, 그것의 내부 데이터를 계산하고, 그것의 force generators를 호출하고, 그러고나서 그것의 위치와 속도를 업데이트하기 위해 integrator를 호출한다. 우리는 그 파티클에 대한 contacts를 축적시키고, 모든 파티클에 대한 모든 contacts를 collision resolver로 넘긴다.

이 프로세스를 더 쉽게 하기 위해서, 우리는 어떤 개수의 rigid bodies를 보유하는 simple structure를 구성할 것이다. 우리는 linked list에서 rigid bodies를 보유할것이다. 정확히 우리가 force generators로 했던 것과 같이. 이 링크드 리스트는 World class에 포함되고, 전체 의 물리적으로 재현된 세계를 나타낸다:

매 프레임에서, 그 startFrame method는 처음에 호출된다. 그것은 각 오브젝트를 forceaccumulation에 대해 준비시킨다:

추가적인 힘들은 이 method를 호출한 후에 적용될 수 있다.

우리는 또한 contacts를 등록하기 위해 또 다른 시스템을 만들 것이다. 우리가 force generators에서 봤던 것처럼, 우리는 contact detectors에 대한 polymorphic interface를 만든다.

이러한 것들 각각은 world로부터 차례로 호출되고, addContact 메소드를 호출하여, world에 그것이 찾은 contacts를 다시 기여한다.

물리를 실행하기 위해, 그 runPhysics 메소드가 호출된다. 이것은 힘을 적용시키기 위해 모든 force generators들을 호출한다. 그러고나서 모든 오브젝트의 적분을 수행하고, contact detectors를 작동시키고, 최종 contact list를 해결한다:

우리는 게임의 각 프레임의 시작에서 startFrame에 대한 호출을 하고, 우리가 물리가 일어나기 원하는 곳에서 runPhysics에 대한 호출을 한다. 일반적인 게임 loop는 이렇게 보일 것이다:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
void loop()
{
    while(1)
    {
        // Prepare the objects for this frame.
        world.startFrame();

        // Calls to other parts of the game code
        runGraphicsUpdate();
        updateCharacters();

        // Update the physics.
        world.runPhysics();

        if(gameOver) break;
    }
}


8.2 Using The Physics Engine
우리는 mass-aggregate engine의 유용한 프로그램을 볼 것이다: particle mass와 hard constraints로 된 구조물들을 만드는 것. 이 테크닉을 사용하여, 우리는 많은 더 큰 오브젝트들을 만들고 재현할 수 있다. 그 가능성은 끝이 없다: 상자; 기계 장치; 심지어 사슬 과 자동차; 또는 spring을 추가하여, 부드러운 변형가능한 blobs

8.2.1 Rope-Bridges And Cables
Sagging bridges, cables, 그리고 휘어진 플랫폼들은 모두 플랫폼 게임 장르의 모두 충실한 일꾼이다. 뿐만 아니라 다른 장르에서 적용될 수도 있다.

우리는 cables에 의해 매달려진 파티클들의 쌍을 사용하여 bridge를 설정할 수 있다. 그림 8.1 이 효과를 갖는 배치를 보여준다. 다리를 따라서 있는 파티클들의 각 쌍은 그것들을 이웃과 연결하도록 유지하기 위해 rod constraint로 연결되어 있다. 파티클들의 쌍은 마찬가지로 bridge에 어떤 강도를 주기 위해 연결되어져있다. 그 케이블들은 공간에서 고정된 점에서 내려가는 cable constraints이다.

bridge demo는 작동하는 이 설정을 보여준다. 너는 한 오브젝트 (캐릭터를 나타내는)를 다리 위에서 움직일 수 있다. 그 collision detector는 그 오브젝트가 그것들 위에 있을 때 가장 가까운 파티클들에 대해 contacts를 적용한다. 그 bridge stretch에 유의하고, 무거운 오브젝트가 있는 것에 순응해라. 데모에서, 그 constraints는 simulation에서 lines으로 보여진다.

collision detector는 몇 가지 설명이 필요하다. 왜냐하면 우리는 오직 우리의 시뮬레이션에서 파티클들만이 필요하지만, 우리는 다리의 인상을 주길 원한다. 그것은 우리를 흥미롭게 하는 파티클 사이의 충돌이 아니라, 캐릭터와 다리의 널빤지 사이의 충돌이다. 우리는 이것을 하는 것의 좀 더 튼튼한 방식으로 책에서 나중에 돌아올 것이다. 이 챕터의 목적으로, 나는 custom collision detector를 만들었다.

그 detector는 캐릭터를 한 구로 다루고, 그것이 어떤 plank와 교차하는지를 보기 위해 체크한다. 한 plank는 파티클들의 한 쌍 사이의 line segment이다. 만약 그 object가 교차한다면, 그러면 캐릭터 오브젝트와 plank particles의 가장 가까운 것 사이에 한 contact가 생성된다. 그 contact normal은 오브젝트의 위치와 plank의 line을 기반으로 설정된다.

Tiltling platforms는 같은 이론을 사용할 수 있다. 그림 8.2는 적절한 구조물을 보여준다. platform demo는 작동하는 이 것을 보여준다: 그 플랫폼은 기본적으로, 한 방향으로 굽어져 있을 것이다. 한 무게는 반대편에 더해질 수 있고, 그것이 굽어지도록 야기시킨다. 그 플랫폼의 pivot을 구성하는 파티클들은 움직이지 않게 하기위해 무한의 질량을 가진 것으로 설정된다. 만약 그 플랫폼이 움직이도록 의도된다면, 그것들ㄹ을 다른 파티클들과 유사한 질량을 가진 것으로 설정될 수 있다.

그 simulation setup은 bridge demo와 유사하다; 너는 둘 다에 대한 풀 소스코드를 볼 수 있다.

8.2.2 Friction
이 접근법의 한 가지 주된 제한은 우리의 contact model에서 마찰이 없다는 것이다. 이 단계에서 마찰을 제외시킨 것은 신중한 선택이였다: 우리는 그것을 part V에서 엔진의 일부로서 구현할 거싱다. 만약 너가 mass aggregates를 만든다면, 그것들은 마치 얼음 위에서 스케이트 타듯이 땅 위에서 미끄러지는 것 처럼 보일 것이다. platform demo의 infinite masses을 바꾸려고 시도해보고, 그 플랫폼이 미끄러지는 것을 보아라.

만약 너가 오직 mass-aggregate physics system만을 구현하려고 의도한다면, 그러면 chapter 15로 넘어가는게 가치있다. 거기에서 마찰에 대해 이야기한 것은 쉽게 particle contacts에 적용될 수 있다. 사실, 수학은 좀 더 간단하다: 우리는 contact의 모든 회전 components들을 무시할 수 있다.

particle masses의 가장 간단한 구성을 제외한 어떤 것이든, 어떤 경우에서든지 full physics engine을 구현하는 것이 가치있을지도 모른다. 너는 mass-aggregate system으로 어떤 오브젝트든 만들 수 있지만, constraints의 개수가 증가함에 따라, collision response system에대한 짐도 늘어나고, stiff constraints가 다소 구부러지는 경향도 늘어나라 것이다. hard onstraints의 그룹들이 resolved되려고 경쟁하기 때문이다. full rigid-body solution은 일반적인 물리 시뮬레이션에서 가장 실용적이다. 그 총알을 깨물어서, 파티클에서 회전과 연장된 오브젝트들을 완료하는 쪽으로 이동할 시간이다.

8.2.3 Blob Games
최근에 우리의 엔진으로 따라하기에 쉬운 방식으로 재현된 soft-bodied characters들이 있는 여러 게임들이 있어왔다.

그 independent Gish and the hit PSP game Loco Roco는 파티클들의 한 집합으로 구성된 2D 캐릭터들을 사용한다 (Loco Roco의 경우에, 너가 놀 수록 더 많은 파티클들을 얻는다; Gish의 경우에 항상 3개나 4개가 있는 것 처럼 보인다). 이러한 파티클들은 soft springs를사용하여 함께 연결되어진다. 그래서 그것들은 합리적인 거리로 떨어져서 움직일 수 있다. 너무 멀리 떨어져서 움직이는 것을 피하기 위해, 그 스프링들은 탄성의 한계를 가지고 있다. 그리고 그것들은 막대처럼 행동하고, 더 이상 연장되어질 수 없다 (너는 이 한계를 사용하여 그 blob을 분리하고 더 작은 blob으로 분리할 수 있다).

이 setup의 어려운 부분은 blob의 집합체로서 전체 캐릭터를 렌더링하는 것이다. 2D에서 이것은 한 원을 각 파티클에 겹쳐놓아서 처리도리 수 있고, 그 스프링이 원을 분리하지 않도록하여 된다. 그리고 이것은 soft blob의 인상을 준다. 2D와 3D 둘 다 에서, 너는 metaball implementation을 사용할 수 있다. 많은 3D 모델링 패키지에서 보여지는. 이것은 꽤 복잡한 알고리즘이지만, 작은 수의 질량체에 대해서, 다루기 쉽다. 그 metaball algorithm은 간단하지 않다. 나는 그것을 여기에서 다루지 않을 것이다; 너는 metaballs이 어떻게 작동하는지에 대한 설명을 위해 모델링에 대한 좋은 교재를 볼 수 있다.

blob demo는 Loco Roco-style blob game에 대한 간단한 구현을 준다.

8.3 Summary
다소 번거로울지라도, mass-aggregate physics engine은 몇가지 흥미롭고 복잡한 효과들을 재현할 수 있다. hard and elastic constraints의 혼합으로 결합된 상대적으로 간단한 오브젝트들의 집합들은 특히 이 접근법에 적절하다.

우리가 본 첫 예제인 rope bridges는 몇 년 동안 mass-aggregate approach로 재현되어왔다. 두 번째 예제는 파티클들의 한 집합으로 큰 오브젝트들을어떻게 구성하는지를 보여주었다. 이것이 성공적으로 작동할 지라도, 많은 문제에 취약하다. 많은 파티클과 많은 hard constraints로 구성된 오브젝트들은 다소 불안정할 수 있다; 재현될 때 휘거나 구부려질 수 있다. 최악의 경우에는, 그것들의 constraints가 그것들을 다른 방식으로 잡아당겨서 파티클에서 눈치챌 수 있는 진동이 있을 수 있다.

단일의 큰 오브젝트를 재현하는 더 좋은 방법이 있다. 그것을 파티클로 구성하기 보다, 우리는 그것을 전체적으로 다룰 수 있다. 이것을 하기 위해서, 그러나 우리는 우리의 물리엔진을 극적으로 바꿀 필요가 있을 것이다. 한 오브젝트의 위치, 속도, 그리고 가속도를 재현할 뿐만아니라, 우리는 그것이 움직임에 따라 어떻게 회전 하는지를 고려할 필요가 있을 것이다. 이것은 우리의 물리엔진에 많은 양의 복잡함을 넣을 것이고, 우리에게 적절히 구현하기 위해 이 책의 나머지가 필요하다. Chapter 9는 그 첫 번째 단계를 취해서, 회전에 대한 수학을 소개한다.


===============================================
Chapter 8을 번역했지만,
Mass-Aggregate engine을 시험해보기 위해서, 이제 코드를 작성하려 한다.
하지만, 이제 까지 작성해온 모든 코드를 활용해야 하는데, 이 복잡성으로 인해서
step-by-step으로 demo를 하나씩 작성하여 만들어보려고 한다.

우선 나는 Bridge Demo를 먼저 만들어 보고 싶다.
하지만, 여러가지를 알아야 하는데 일단 다음의 순서로 해볼 것이다.
이 순서는 test를 하는 도중에 계속 바뀔 수도 있다.

순서를 말하기 전에 Bridge가 어떻게 구성되어 있는지 알아보자.

우선 위에서 내려오는 rope에 의해서 밑에 다리가 유지된다.
이 rope는 fixed point에 고정되어 있고 Cable로 구성되어 있다.

demo에 보면 이제 밑의 다리 그러니까 다리의 널빤지는
rodcable의 혼합으로 구성되어 있다.



그러니까 저기에서 파란색 선은 rod이고, 초록색 선은 cable이다. 회색 선은 anchored cable이다. 그림에서 보면 알겠지만, 여러 파티클은 rod, cable, anchored cable에 연결되어 있다.

이 정도면 이제 다음의 constraints를 알아야한다.

anchored cable, cable, rod.

그러면 순서는 이제 정해진다.

1. Anchored Cable 이용해서 fixed point를 간단하게 quad로 그리고, 밑에 있는 파티클을 cube로 렌더링한다. 그리고 이 데모에 구현되었듯이, mass를 다르게 하여 움직임을 실험한다.
2. cable에도 같은 것을 실험한다.
3. rod에도 같은 것을 실험해본다.
4. anchored cable, cable, rod를 합쳐서 운동을 실험해본다.
5. bridge 구조물을 만들어서 실험해본다.

이 정도면 될 것이다. 이제 각각의 순서에 대해 코딩을 하고, 그것의 결과물을 보이도록 하자.

우선 1번을 실행하기 위해서는 particleworld에 particle, constraint등의 정보를 넣어 시작해야 한다. 다음의 코드로 기본 설정을 할 수 있다.


// Particle World
// 1. Initialize the physics world
GPED::ParticleWorld chanPhysicsWorld(1);

// 2. Initialize the particle and push it to the physics world
GPED::GPEDParticle chanParticle;
chanParticle.setPosition(glm::vec3(0.f, 8.f, 0.f));
chanParticle.setVelocity(glm::vec3(0.f));
chanParticle.setDamping(0.9f);
chanParticle.setAcceleration(glm::vec3(0.f, -10.f, 0.f)); // Gravity
chanParticle.clearAccumulator();
chanPhysicsWorld.getParticles().push_back(&chanParticle);

// 3. Initialize the constraint and push it to the physics world
GPED::ParticleCableConstraint chanAnchoredCable;
glm::vec3 fixedPoint = glm::vec3(0.f, 15.f, 0.f);
chanAnchoredCable.particle = &chanParticle;
chanAnchoredCable.anchor = fixedPoint;
chanAnchoredCable.maxLength = 5.f;
chanAnchoredCable.restitution = 0.5f;
chanPhysicsWorld.getContactGenerators().push_back(&chanAnchoredCable);

그런데 이렇게만 하니, CableConstraint로서 기본 길이로만 유지는 잘 했다. 하지만, 움직임을 보여주지 않아 그냥 Rod도 하나 추가했고, Visual을 잘 나타내기 위해 line segment를 그리는 geometry shader를 추가했다:


// Particle World
// 1. Initialize the physics world
GPED::ParticleWorld chanPhysicsWorld(2);

// 2. Initialize the particle and push it to the physics world
GPED::GPEDParticle chanParticle;
chanParticle.setPosition(glm::vec3(0.f, 8.f, 0.f));
chanParticle.setVelocity(glm::vec3(0.f));
chanParticle.setDamping(0.9f);
chanParticle.setAcceleration(glm::vec3(0.f, -10.f, 0.f));
chanParticle.clearAccumulator();
chanPhysicsWorld.getParticles().push_back(&chanParticle);

GPED::GPEDParticle chanParticle2;
chanParticle2.setPosition(glm::vec3(4.f, 8.f, 0.f));
chanParticle2.setVelocity(glm::vec3(0.f));
chanParticle2.setDamping(0.9f);
chanParticle2.setAcceleration(glm::vec3(0.f, -10.f, 0.f));
chanParticle2.clearAccumulator();
chanPhysicsWorld.getParticles().push_back(&chanParticle2);

// 3. Initialize the constraint and push it to the physics world
GPED::ParticleCableConstraint chanAnchoredCable;
glm::vec3 fixedPoint = glm::vec3(0.f, 15.f, 0.f);
chanAnchoredCable.particle = &chanParticle;
chanAnchoredCable.anchor = fixedPoint;
chanAnchoredCable.maxLength = 5.f;
chanAnchoredCable.restitution = 0.5f;
chanPhysicsWorld.getContactGenerators().push_back(&chanAnchoredCable);

// I just added this Rod Constraint to visualize the physics run.
GPED::ParticleRod chanRod;
chanRod.length = 3.f;
chanRod.particle[0] = &chanParticle;
chanRod.particle[1] = &chanParticle2;
chanPhysicsWorld.getContactGenerators().push_back(&chanRod);
// Particle World

lineShader.vs:
// shadertype=glsl
#version 330 core

layout (location = 0) in vec3 aPos;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

uniform vec3 toPoint;

out VS_OUT
{
 vec4 normal;
 float dist;
}vs_out;

void main()
{
 vec3 WorldPos = vec3(model * vec4(aPos, 1.0));
 gl_Position = projection * view * vec4(WorldPos, 1.0);

 vs_out.normal = normalize(projection * view * vec4(normalize(vec3(toPoint - WorldPos)), 0.0));
 vs_out.dist = length(vec3(projection * view * vec4(toPoint,0.0))
      -vec3(projection * view * vec4(WorldPos, 0.0)));
}
lineShader의 vertex shader에서 하는 것은 WorldPos가 fromPoint이고, toPoint의 월드좌표계상의 위치를 통해서, from ~ to로 가는 normal과 그것의 거리를구한다.
여기에서 주의할 것은 geometry shader로 넘겨줄 때, normal를 vec4로 선언하는 것이다. vec3로 선언하면 카메라의 움직임에 따라 무언가 이상하게 된다. 이것을 이렇게 하라고 한 것은 LearnOpenGL geometry shader 파트의 댓글에서 사람들의 솔루션이 있어서 참고했다.

lineShader.gs:
// shadertype=glsl
#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 2) out;

const float width = 5;

in VS_OUT
{
 vec4 normal;
 float dist;
}gs_in[];

void main()
{
 gl_Position =  gl_in[0].gl_Position;
 EmitVertex();

 gl_Position =  gl_in[0].gl_Position + gs_in[0].normal * gs_in[0].dist;
 EmitVertex();
 
 EndPrimitive();
}
그래서 첫 번째 점을 EmitVertex 해주고, 그 다음의 점을 toPoint의 방향으로 거리만큼 또 다른 한점을 EmitVertex를하고 EndPrimitive로 도형을 그리는 것을 끝낸다. out layout을 line_strip과 max_vertices = 2로 하여 선분을 그릴 수 있게 했다.

{
line shader를 구성하면서 line width를 조절하는 것을 찾아보았는데
https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
여기에 어떤 사람이 사람들과 이야기하면서 발전하는 것을 보여준다.

그림을 보면 대충 로직을 이해할 수 있는데, from에서 to 까지의 normal과 line width 설정한 것을가지고 그것 방향의 위 아래로 line을 늘리는데, 그것을 통해서 사각형을 만들어서, line width의 두께를 조절한다.

소스코드도 올려놨으니 가져다 써도 될 듯하다. 또는 나의 geometry 구현의 실력을 높이기 위해서 만약 그런 thickness의 조절이 필요하다면 실제로 구현해볼만 하겠다.
}

renderline() code in main():

unsigned int lineVAO = 0;
unsigned int lineVBO;
void renderline()
{
 if (lineVAO == 0)
 {
  float lineVertices[] =
  {
   0.f, 0.f, 0.f,
  };

  glGenVertexArrays(1, &lineVAO);
  glGenBuffers(1, &lineVBO);
  glBindVertexArray(lineVAO);
  glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(lineVertices), &lineVertices, GL_STATIC_DRAW);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
 }

 glBindVertexArray(lineVAO);
 glDrawArrays(GL_POINTS, 0, 1);
 glBindVertexArray(0);
}


결과:

yellow line은 Anchored Cable이고, blue line은 rod이다.
빨간색 quad는 fixed Point이다.
처음에 Anchored Cable이 maxLength보다 더 긴데, 시뮬레이션이 시작하자마자,
본인의 위치로 돌아가고, rod도 본인의 maxLength보다 긴데, 자기 자리로 돌아가고,
rod에 연결된 파티클들은 중력에 영향을 받기 때문에, rod는 움직이게 된다.
그리고 나는 yellow line에 연결된 particle에 mass를 시뮬레이션 도중에 증가시켰다.
그래서 처음에 진자운동이 크게 움직였으나, mass가 증가하고나서 부터 확실히 줄어들었다.

이것을 한 번 해보니, 1~4번까지 그냥 간단하게 straight로 통과되는 느낌이다. 바로 bridge로 넘어가야겠다.

그런데 line segment를 그릴 때, 조금 불편함이 있다. 이 책의 제작자는 class를 통해서 모든 것을 해결하기 때문에, 계속해서 상속받아서, 파티클들에 더욱 쉽게 접근하지만,
나는 우리가 나중에 rendering할 것을 고려해야 하기 때문에, 아직 그런 구조를 만들기가 싫다.  그래서 앞으로 chatper가 좀 더 많이 남았는데, 이런 line segment를 좀 더 편하게 그리도록, access에 대한 방법을 고칠 필요가 있다. 그냥 간단히  getPositionPointer()라는 method를 만들어서 해야겠다. OOP의 패턴에는 불합리한 메소드이겠지만.




일일이 다 구성하기 귀찮아서, 소스코드에 있는 설정은 그대로 복붙했다.
line segment는 다음의 구성에 담아서, rendering 하는데 썼다.
Yellow line은 Anchored Cable,
Green line은 Cable,
Blue line은 Rod이다.

// 4. line segment 
std::vector<std::pair<glm::vec3, std::pair<glm::vec3*, glm::vec3*>>> fromtoLine; // color, position position
for (unsigned i = 0; i < 10; ++i)
{
 fromtoLine.push_back(std::make_pair
 (
  glm::vec3(0.f, 1.f, 0.f),
  std::make_pair
  (
   cables[i].particle[0]->getPositionPointer(),
   cables[i].particle[1]->getPositionPointer()
  )
 ));
}
for (unsigned i = 0; i < 12; ++i)
{
 fromtoLine.push_back(std::make_pair
 (
  glm::vec3(0.98f, 0.88f, 0.f),
  std::make_pair
  (
   supports[i].particle->getPositionPointer(),
   &supports[i].anchor
  )
 ));
}
for (unsigned i = 0; i < 6; ++i)
{
 fromtoLine.push_back(std::make_pair
 (
  glm::vec3(0.f, 0.f, 1.f),
  std::make_pair
  (
   rods[i].particle[0]->getPositionPointer(),
   rods[i].particle[1]->getPositionPointer()
  )
 ));
}

이것을 하면서 문제가 생겼는데, 갑자기 파티클들이 엄청난 속도로 튀어올라, contraints가 제대로 동작을 안했었다. reset 기능을 추가하여, reset을 해봤는데 그런 일이 없었다.
그래서, 내가 예측하는 문제점은 euler integration의 부정확성으로 인해 초반에 문제가 되는 것 같다. 그냥 glfwgettime으로 이것을 하고 있는데, 이것으로 인해 문제가 생기는 것 같다.

그래서, 내 생각에는, 복잡하지만 이 책이 time managing 코드를 보고 random 클래스처럼 공부를 해서 쓸 필요가 있다. 웬만한 고급 물리 엔진에는 다 그런식으로 time 관리를 하는 것 같더라.

이 mass-aggregate engine part에 platform, blob 데모가 다 있지만, 이것만으로도 충분한 것 같다. 어서 rigid body engine으로 넘어가서 어려운 것들에 시간을 많이 쏟는게 나을 것같다.

전반적인 구조는 익혔으니, physics engine의 더 깊은 내용을 공부할 준비는 된 것 같다.

댓글 없음:

댓글 쓰기