본문 바로가기

Houdini/Houdini1_Rigidbody

RIGID BODY_03 RIGID BODY SOLVER 종류와 특징 - Ep03. rbd / bullet Solver 그리고 RIGID BODY SOLVER


위 두 가지 solver의 공통점

  • 오브젝트와 소스가 나뉘어있다는 점
  • 기본적으로 파티클이나 불, 연기등은 생성과 소멸이 반복되기 때문에 마치 땔감을 넣어주듯이 solver 작동을 위해 소스를 계속 투입해줘야 한다.
  • 소스가 계속 투입되지 않으면 새로운 파티클(혹은 smoke)은 만들어지지 않고, 이미 생성된 파티클(혹은 smoke)만 가지고 물리작용을 일으킨다.

 

맨 왼쪽의 세팅은 rigid body 시뮬레이션이 발생하기 위한 기본적인 세팅이다.

  • 앞의 두 케이스(파티클, smoke)와 다른 점은 소스를 투입하는 것이 없다는 점이다.
    • rigid body 시뮬레이션의 목표를 생각해 보면 이해가 간다.

 

가장 기본적인 상황에서 rigid body 시뮬레이션의 목표는 dop network 밖에서 준비된 물체가 물리법칙에 의해 어떻게 떨어지고, 어떻게 충돌하는지, 어떤 리액션을 보이는지 보는 것이다.

 

solver 위에 연결된 노드(위 이미지의 rbd packed object)는 dop network 밖에서 준비된 물체를 불러오는 노드가 될 것이다.


dop network 밖에 어떠한 물체 A, B, C가 있다고 할 때, 이 물체들을 merge로 묶어준 뒤, 이 결과를 dop network 안에서 rbd object로 불러오는 것과, 각각의 물체를 rbd object 노드 세 개에 1대 1로 대응해서 dop network 안에서 merge로 묶어준 것은 세팅이 다르다.

rigid body solver의 계산 결과 또한 다르다.

 

위와 같은 세팅이라고 했을 때, 세 개의 박스는 일반적으로 다른 세팅을 안 바꾼다는 가정하에 시뮬레이션의 시작시점에 바로 들어오게 된다.(한 번에 세 개가 보이게 된다.)

 

하지만, 우리가 원하는 것이 한꺼번에 박스가 나타나는 것이 아닌, 순차적 혹은 랜덤 하게 박스가 다른 시점에 생성되거나 하기를 원한다면? 

생성규칙을 정해주기 위해서 sop solver를 다룰 줄 알아야 한다.

rigid body 시뮬레이션은 우리가 그릇에 올린 내용물들이 충돌하고 물리법칙에 따른 리액션을 보여주기 바라는 것이다.

이때, 그릇에 물체를 올리게 되는 규칙을 sop solver로 조절이 가능하다.

 


세팅하기에 따라 다르다.

물체가 하나의 오브젝트에 올려졌는데, 각각 따로 움직일 수도 있고, 한번에 묶여서 움직일수도 있다. 

왜 이렇게 '때에 따라 다르다'라고 하느냐면, rigid body 시뮬레이션을 발생시키는 solver와 오브젝트가 하나씩만 있는 것이 아니기 때문이다.


rigid body의 핵심은 '충돌'이다.

이 충돌이 어떤 조건으로 이뤄지는지에 따라 solver가 나뉜다.

 

rbd solver

  • 볼륨을 기반으로 하는 충돌 시뮬레이션
  • 충돌의 조건은 SDF이다.
    • 해상도가 높으면 높을수록 정확도는 올라가지만 당연하게도 느려진다.(용량이 커진다 = 무겁다)
  • 약점은 느리다는 점이다.
    • 모든 물체가 볼륨으로 컨버팅 되는 과정이 필요하고 볼륨의 정보량의 사이즈에 따라 시뮬레이션 속도에 너무 많은 영향을 준다.
  • 볼륨 데이터를 준비해 주거나, 볼륨의 해상도에 대해 고민을 해야 할 것이다.
  • constraint와의 궁합이 좋지 않다.

 

bullet rbd solver

  • 충돌의 조건은 지오메트리 자체이다.
  • 계산속도가 빠르다.
  • 물체를 다른 지오메트리로 대체해서 쉽게 쉽게 계산을 해주기 때문에 대체해 주는 지오메트리의 모양에 따라 결과가 부정확할 수 있다는 약점이 있다.
    • 복잡한 물체라면 간단한 지오메트리로 대체해서 충돌을 일으키기 때문에 빠른 시뮬레이션이 가능하지만, 그만큼 정확도는 아쉬울 수 있다.(이 부분에 대해 개선이 필요하다.)
  • 그릇에 올린 물체가 어떠한 지오메트리로 대체되어 시뮬레이션이 계산될지 고민을 해야 할 것이다.
  • constraint 작업을 하기에 특화되어 있다.
    • 복잡한 연결관계를 가진 시뮬레이션에서 사용하기 용이하다.

 

둘 중 어느 solver가 더 좋다고는 말하지 않는다.

  • 둘의 원리 자체가 다르기 때문이다.

 

rigid body solver

  • rbd solver와 bullet rbd solver를 묶어놓고 골라서 사용하게끔 만들어놓은 solver이다.

solver engine이 bullet일 경우, bullet tap이 활성화되고, RBD tap은 비활성화된다.(반대의 경우도 마찬가지이다.)

 

어떤 solver가 더 낫다고는 말하지 못하지만, 우리는 bullet solver를 더 많이 사용할 예정이다.

그 이유로는 이후에 다루게 될 constraint 때문이다.

  • constraint : 물체들 간의 연결관계
    • ex) 두 물체가 있을 때, 이 물체들은 서로 딱딱하게 위치와 각도가 고정되어 있을 수도 있고, 말랑말랑하게 위치와 각도가 고정되어 있을 수도 있으며, 두 물체가 접착되어 있다가 일정량 이상의 충격이 가해졌을 때 떨어져 나갈 수도 있다. 이런 연결관계를 constraint라고 한다.
  • constraint를 얼마나 잘 다루느냐에 따라 rigid body 시뮬레이션의 퀄리티가 엄청나게 많이 바뀐다.
    • 얼마나 자연스러운 결과를, 얼마나 흥미로운 결과를 얻어내는지가 constraint에 달려있다.
  • constraint 작업은 노골적으로 bullet solver에서 수행을 해야 올바르게 적용이 가능하다.

dop network 안으로 소스를 불러올 때 어떠한 일이 발생하는지 알아보자.

우리가 준비하는 오브젝트가 dop network안으로 들어가서 어떻게 인식하는지 보자.

 

rigid body 시뮬레이션의 두 가지 작동방식

  • 볼륨
  • 지오메트리

각각의 방식에 맞게 주어지는 물체가 충돌조건으로 올바르게 치환되어야 하는데, rbd에서는 어떻게 치환되고, bullet에서는 어떻게 치환되는지 확인해보려 한다.

 

RBD solver 혹은 RBD engine으로 rigid body solver를 작동시킨다면, SDF가 필요하다.

만약 SDF를 dop network 안에서 보고 싶을 때는 지오메트리로 변환해서 사용자에게 보여주게 된다.

 

위의 상태가 RBD solver로서 실제 rigid body 시뮬레이션에 쓰이게 될 데이터이다.

 

dop network 안에서 충돌조건을 보고자 한다면, 위의 이미지처럼 보여주지는 않는다.

  • 위의 자료를 iso surface로 보여주게 된다.

위와 같은 형태로 사용자가 충돌조건을 체크하면서 RBD 스타일로 작업을 진행하게 된다.(위의 이미지는 해상도가 너무 낮은 상태이다.)

 

현재 해상도를 결정해 주는 것은 iso offset의 uniform Sampling Division parameter이다.(몇 개로 쪼개느냐)

 

두 가지 충돌조건이 얼마큼의 메모리를 할당하고 있을까?

오해하지 말자. dop network 안에서 우리 눈에 보이기로는 위와 같은 Iso Surface 형태로 보이지만, 실제 시뮬레이션에서는 visualize 되는 폴리곤이 가지는 용량이 중요한 것이 아니고, SDF 볼륨정보의 용량이 중요하다.

Uniform Sampling Division 10의 SDF 볼륨정보, 메모리는 5.95KB로 굉장히 가볍다.
Uniform Sampling Division 50의 SDF 볼륨정보, 메모리는 363.96KB
Uniform Sampling Division 200의 SDF 볼륨정보, 메모리는 22.56MB로 확 뛰었다.

 

우리가 직접 프록시 볼륨을 만들어주는 방법도 있었다.

Voxel Size 0.03 SDF 볼륨정보, 메모리는 2.87MB

 

이 상태에서 러버토이의 사이즈를 두배로 키운다면?

iso offset으로 SDF를 만들어준 정보는 메모리 사이즈에 큰 변화가 없다.

하지만 VDB from Polygons로 만들어준 SDF는 메모리 사이즈도 두 배정도로 커졌다.

rubber toy size 2배, Uniform Sampling Division 200의 SDF 볼륨정보, 메모리는 22.56MB
rubber toy size 2배, Voxel Size 0.03 SDF 볼륨정보, 메모리는 4.42MB

두 경우가 SDF를 구하는 방식이 달라서 용량차이가 발생하는 것이다. 

  • Iso Offset에서 몇 개로 쪼개느냐는 사이즈에 상관없이 쪼개는 양이 정해져 있다.
    • 그래서 크기와 관계없이 정보량이 같다.
  • VDB from Polygons는 voxel size로 쪼갤 길이를 정하는 경우에는 크기가 바뀌면 용량도 바뀐다.

우리가 유추할 수 있는 것은

볼륨으로 작업을 할 때 크기가 다른 물체를 다룸에 있어서 사이즈의 차이가 많이 난다면, 충돌조건의 해상도를 잘 설정해줘야 한다. 

사이즈가 큰 경우에는 울퉁불퉁한 디테일이 많은 벽일 때, Iso Offset 방식은 디테일을 많이 잃게 된다. 반대로 VDB from Polygons을 사용하면 용량이 너무 클 수도 있다.

사이즈가 작아서 어느 정도 무시가 가능한 디테일인 경우, Iso Offset 방식(개수로 쪼개는 방식)은 쪼개는 개수가 과할 경우, 불필요하게 용량이 클 수 있다.

 

 

이번에는 bullet에서 쓰이게 될 데이터를 만들어보자.

 

Bullet은 변환과정이 상대적으로 쉽다.

일단 볼륨으로 변환하는 과정이 없다.

지오메트리 그 자체로 충돌을 발생시킬 수 있다.

만약에 rubber toy가 지금 가지고 있는 모든 디테일을 전부 살려서 작업을 하고 싶다면, 그냥 이대로 사용해도 무방하다.

주어지는 원본 그 자체를 고스란히 쓰는 경우, 이러한 방식을 부르는 이름이 있는데, 'CONCAVE'라고 한다.

위와 같은 방식의 경우 문제는 bullet solver의 장점인 빠른 속도가 나오질 않는다.

CONCAVE의 용량은 2.38MB

bullet solver가 계산이 빠른 이유는 지오메트리의 충돌조건을 표현하기 쉬운 가벼운 지오메트리로 전환해서 시뮬레이션하기 때문에 빠른 것이다.

 

그렇다면, bullet solver는 어떤 방식으로 물체를 가벼운 충돌조건으로 변환시킬까?

  • convex hull 방식이다.

보자기 싸놓은 것 같다.

Convex Hull Node

  • 물체를 마치 랩핑 하듯이 가장 튀어나온 부분들을 기준으로 감싸놓는다.
  • convex hull을 이용할 경우, 우리가 이용하게 될 충돌 지오메트리는 104.99KB로 매우 작아진다. (concave 일 때 2.38MB)
  • 치명적인 단점이 존재한다.
    • convex hull이 적용된 물체가 다른 물체와 상호작용을 할 때, convex hull의 특징 때문에 시뮬레이션의 정확도가 떨어지게 된다. 
      • 가장 튀어나온 부분을 기준으로 물체를 감싸기 때문에 안으로 들어간 부분은 절대로 다른 물체와 충돌할 수 없다.

 

convex hull 말고도 bullet solver가 더 빠르게 계산을 할 수 있는 방법도 있다.

  • 충돌조건을 단순화시켜 주는 것이다.
  • bound 노드를 사용해서 rubber toy를 대체할 충돌조건으로 만들어줄 수도 있을 것이다.

bound 노드를 활용한 충돌처리의 경우, 시뮬레이션의 정확도는 매우 낮아지겠지만, 이러한 방법도 사용될 수 있다.

  • 만약 하늘에서 rubber toy 1000개가 떨어진다고 했을 때, rubber toy 하나하나의 충돌의 디테일을 보는 것이 아닌 경우라면, 빠르게 시뮬레이션될 수 있도록 충돌처리를 단순화시켜서 '아, 충돌이 일어나고 있구나.' 하는 느낌을 내도록 할 수 있을 것이다.

CONCAVE에 비해 용량이 대략 1/22 정도로 줄어들었다.(그만큼 시뮬레이션이 빠를 것이다.)
Convex Hull을 사용했을 때보다도 용량이 1/30 정도로 줄어들었다.
Bound > Box를 사용했을때보다도 메모리 사용량이 적다.

 

convec hull의 약점을 보완할 수 있는 방법을 알아보자.

Tommy에 convex hull을 적용한 결과이다.

다리 사이, 팔과 몸통 사이 공간이 막혀있는 것이 아쉽다. 이것을 보완해 보자.

 

원리는 간단하다.

tommy를 쪼개주고, 각각의 쪼갠 파츠에 대해 convex hull을 적용해 준다.

convex hull의 디테일을 높이고 싶을 경우, scatter로 뿌려지는 포인트의 개수를 늘려주면 더 잘게 쪼개고 convex hull을 만들어낼 것이다.

 

또 하나의 방법으로는 오브젝트를 볼륨으로 만들어주고, scatter로 포인트를 뿌린 뒤, sphere를 각 포인트에 복사해 줘서 오브젝트와 유사한 모양을 띄도록 여러 개의 sphere로 대체해 주는 것이다.


정리

  • 충돌조건을 만드는 방식에 따라 쓰게 될 solver가 바뀐다.
  • 우리는 앞으로 bullet solver에 집중하게 될 것이다.
    • 사용하기에 따라 매우 빠른 시뮬레이션이 가능하다.
    • 나중에 다루게 될 constraint와 합이 잘 맞기 때문이다.

rigid body 시뮬레이션을 구동해 보자.

 

dop network 안에서 dop network 밖의 물체를 불러오는 여러 노드들이다.

 

가장 많이 다루게 될 노드는 RBD Packed Object 노드이다.


Static Object

  • dop network 안에서 다른 물체들의 충돌조건이 되는 물체
  • 충돌이나 중력의 영향을 받지는 않는다.
    • 그래서 노드의 UI도 벽처럼 묘사되어 있다.

만약 static object를 RBD solver에 연결하게 된다면, 우리가 신경 써야 할 부분은 Collision tap > RBD Solver tap 안의 내요이다.

static object가 bullet solver에 연결되어 있다면, Collision tap > Bullet tap 안의 내용을 신경 써줘야 한다.


RBD Object

  • rigid body 시뮬레이션을 위한 오브젝트 중 가장 범용적이고 가장 대중적인 노드이다.

static object와 마찬가지로 어느 solver에 연결하느냐에 따라(RBD / Bullet) 집중해서 봐야 할 collision의 내용은 각각 RBD / Bullet이 된다.


RBD Packed Object

  • 외부에서 pack 된 자료를 불러와줄 때 사용하는 노드이다.
  • 다른 노드들과 다르게 collision이 두 개로 나뉘지 않고 bullet data만 사용이 가능하다.


RBD Fractured Object

  • 조각이 나있는 물체를 넣어줄 때 사용되는 노드이다.

static object, RBD object와 마찬가지로 어느 solver에 연결하느냐에 따라(RBD / Bullet) 집중해서 봐야 할 collision의 내용은 각각 RBD / Bullet이 된다.

 

확실하게 개념을 잡고 기억해서 앞으로 오브젝트를 solver에 연결할 때 연결을 해도 되는지 안되는지 고민하는 시간낭비를 하지 않기를 바란다.


일단 위의 두 가지 object(static object / RBD object) 노드를 가지고 외부의 물체를 불러와보도록 하자.

위와 같이 Box, Rubber toy를 만들어주고, static object로 dop network 안에 box를 불러왔다.

dop network의 시작프레임은 11 프레임으로 맞춰줬다.

그리고 위의 이미지처럼 중력이 적용되도록 gravity 노드를 연결해 놓았다.

11 프레임에서 뿅 하고 나타나지만 중력이 적용되어서 떨어지거나 하지는 않고 있다.

위에서 이야기했듯이 다른 물체의 충돌 조건은 되어주지만, 중력의 영향을 받거나 하지는 않는다.

 

box의 충돌처리를 보고 싶다면, Static Object의 Collisions tap에서 RBD Solver 부분을 확인해 보면 된다.

Uniform Divisions 값에 따라서 충돌을 일으키는 볼륨의 해상도가 변하게 된다.

 

만약 Static Object를 Bullet Solver에 연결하게 된다면?

  • RBD solver의 볼륨으로 만든 collision guide는 준비는 되지만, 충돌조건으로 사용되지는 않는다.

bullet solver에 연결하였고, 위의 이미지는 static object의 collisions > bullet data의 geometry guide를 켜준 모습이다.

rubber toy를 불러와보면 더욱 확실하게 확인이 가능하다.


RBD Object 노드를 사용해서 Dop Network 밖의 물체를 불러와보자.

rbd packed object 노드는 왜 저기있지...

바닥과의 충돌을 위해 ground plane을 연결해 줬다.

toy를 불러와보자.

이번에는 RBD Object를 Bullet solver에 연결해 보자.

우리에게 중요한 가이드는 이녀석이 아니다.
이 convex hull이 적용된 녀석이다.

충돌방식이 바뀌었고, solver가 바뀌게 되면서 동일한 위치에서 떨어지고 있지만, 시뮬레이션의 결과가 다르게 나온다.

RBD solver의 결과
Bullet solver의 결과

rigid body solver에서 engine만 골라서 선택해 주면 RBD / Bullet solver의 결과를 얻을 수 있다.


이번에는 rubber toy와 box가 같이 떨어지도록 해보자.

RBD solver 적용
Bullet solver 적용

두 solver의 결과 중 어떤 것이 더 낫다라고 판단할 수는 없다.

이미 둘 다 자연스러운 시뮬레이션 결과이기 때문이다.


이번에는 두 물체가 서로 부딪히도록 세팅해 보자.

RBD solver 충돌
Bullet solver 충돌

RBD / Bullet solver의 충돌결과가 많이 다르다. 그 이유로는 bullet data의 경우 convex hull이 적용되면서 toy를 랩핑 하게 되고, 그 위를 box가 미끄러지듯이 흐르기 때문이다.

같은 프레임의 RBD solver 가이드의 모습

RBD solver로 시뮬레이션한 결과를 guide로 보면, box가 rubber toy의 등 쪽을 누르는 모습을 볼 수 있다.

Bullet solver 시뮬레이션에서는 이 부분에 대해 convex hull 표면을 따라 box가 흘러 내려가버리는 모습이다.


세상에... 다른 것들에서 시뮬레이션을 작업할 때 자주 보던 convex hull에 대해 이처럼 명쾌한 설명이라니...

드디어 convex hull을 이해했다...

왜 때문에 그때 작업했던 시뮬레이션들이 그렇게 결과를 도출했는지도 드디어 이해하게 되었다.

파티클을 지나 볼륨을 넘어서 rigid body 초입까지 도달한 지금, 매우 즐겁고 행복하다. 내가 배우고 익힌 내용들을 가지고 만들어가게 될 것들에 대해 상상해 보는 것이 즐겁다.

 

물론 만들기 시작하면 어디에선가 곡소리를 내면서 내가 왜 그랬을까 왜 그랬을까를 반복하며 시뮬레이션하고 렌더 걸고 그러겠지만...

 

지금 기분이라면 그러한 모든 트윜들도 즐길 수 있을 것 같다. :)