본문 바로가기

Houdini/Houdini1_Rigidbody

RIGID BODY_17 캐릭터의 충돌조건 - Ep17. mixamo 캐릭터로 충돌조건 만들기


Mixamo 에서 자료를 다운받는다.

https://www.mixamo.com/#/

 

Mixamo

 

www.mixamo.com

 

첫번째로 Mutant 캐릭터의 Mutant Swiping 애니메이션을 받았다.

두번째는 우리의 친구 Brute 캐릭터의 Standing Melee Combo Attack Ver.1 애니메이션을 받았다.

 

두 파일은 원하는 곳에 옮겨놓는다.

 

앞으로는 초반에 구비해둬야하는 자료가 많다.
미리 정의해뒀던 자주 사용하는 노드들의 집합 'a00'도 필요하고, 충돌에 쓸만한 데이터를 최대한 미리 불러놓고 작업을 진행해야할 것이다.
원하는 다른 자료가 있을 경우, 미리 준비해둘 것!!

 

Mutant를 불러오자.

 

File 노드를 이용해서 불러올 경우, 사이즈가 상당히 크게 들어오게 된다. transform 노드를 사용해서 스케일을 줄여준다.(0.01)

  • 하지만 이 경우는 애니메이션이 적용된 상태는 아니다.

 

Agent 노드를 활용해서 불러오자.

input은 FBX
packing 된 데이터로 불러오게 된다.

 

오늘의 핵심은 '이 캐릭터가 다른 물체와 어떻게 충돌하도록 세팅을 하느냐' 이다.

 

volume을 다룰 때를 생각해보자.

volume의 충돌 조건은 SDF(Signed distance field)이다. 그래서 화질이 좋은 결과를 얻어내기 위해서는 voxel의 사이즈를 낮춰가면서 결과를 얻어야했다.

 

하지만 오늘은 이 방식을 사용할 수 없다.

  • Rigidbody solver는 기본적으로 packing된 자료를 요구하기 때문에 다른 방법이 필요하다.

지금까지의 작업방식과 달라야 하는 결정적 이유로는,

  • 여지껏 작업한 내용을 보면, 각각의 조각의 모양이 아예 바뀌는 케이스는 없었다. 
  • 하지만, 이번 작업처럼 캐릭터가 충돌하기를 바라는 작업에서는 Deforming이 되는 것처럼 모양이 계속 바뀌게 된다. 이래서는 convex hull 방식의 작업도 곤란하고, 그렇다고 concave(원본)방식으로 작업하기엔 시간대비 효율이 매우 나쁘다. 

 

그래서 오늘은 두가지 방식으로써 rigidbody에서 활용하기 좋은 캐릭터의 충돌조건 세팅에 대해 공부해볼 것이다.


첫번째 방식은 캐릭터를 많은 sphere로 대체해주는 방식이다.

추가로 적용되는 기술로는, point deform 노드를 활용해서 sphere로 대체된 mutant 캐릭터가 애니메이션에 맞게 움직이도록 해줄 것이다.

  • 캐릭터를 다룰 때에는 특히나 많은 도움이 될 것이다.
    • 방법은 간단하지만, 효율은 상당히 만족스러울 것이다.

 

필요한 노드를 확인해보자.

 

  • VDB from Polygons : 캐릭터 데이터를 volume 데이터로 바꿔줄 필요가 있다.
  • VDB to Spheres : volume 데이터 안쪽을 sphere로 채워준다.
    • VDB to Spheres에서 가장 중요한 것은 Max Spheres와 Point Count의 밸런스이다.
      • Point Count : 얼마나 많은 포인트를 활용해서 제공받은 volume 정보를 분석하고 안쪽을 sphere로 채울 것인가(point count가 높다면, 보다 고르게 캐릭터 안쪽을 sphere로 채울 수 있다)
      • Max Spheres : 캐릭터 안쪽을 채우는데 최대 몇개까지 sphere를 사용할 것인가?
        • 아무리 분석을 point count를 높여서 빡세게 하더라도 이용가능한 sphere의 개수가 50개로 제한이 된다면, 안쪽을 채우는데 무리가 있다.

 

point deform을 적용할 때 주의사항

  • 기준으로 잡을 타이밍에 마침 캐릭터가 너무 웅크리고 있을 경우, point deform이 예쁘게 작동하지 않을 수 있다.(면이 늘어나거나 움직임에 따라 결과가 찢어져서 표현되는 등)
  • 그래서 기준으로 잡는 타이밍은 캐릭터가 최대한 몸을 펴고 있는 순간을 기준으로 작업을 시작하는 것이 좋다.

 

time shift 노드를 사용해서 원하는 타이밍으로 캐릭터 애니메이션을 고정시킨다.

그리고 VDB from polygons 노드를 사용해서 volume 데이터(SDF)로 변환한다.

VDB to Spheres 노드를 적용한 결과

위의 sphere가 충돌조건으로 사용하게 될 정보이다.

현재 칼날 부분과 손끝 등 충돌조건으로 활용하기에 비어보이는 부분이 많다.

그래서 캐릭터를 얼마나 꼼꼼하게 sphere로 채우는지가 핵심이 된다.

Max Spheres와 Point Count의 밸런스 맞추기

point count가 높으면 높을수록, 원하는 max spheres만큼의 sphere를 가지고 안쪽을 채우게 된다.

  • point count를 상당히 많이 높여서 분석력을 높여준 뒤, 어느정도 필요한 양의 max spheres로 조절해준다.

point count 400,000 / max spheres 2500

convert VDB를 사용해서 polygon으로 만들어준 뒤, Isovalue 값을 조절해서 몸집을 조금 키워줄 수 있다. 이 polygon을 다시 SDF 볼륨정보로 얻어서 sphere를 채울 경우, 기존의 mutant 데이터보다 살짝 몸집이 커진 충돌조건 데이터를 얻을 수 있다.


이제 캐릭터의 움직임에 따라 sphere가 예쁘게 움직여주면 된다.

point deform 세팅을 진행해보자.

첫번째 input은 움직이려는 데이터를 넣어준다.

  • 위에서 만들어준 sphere 데이터를 연결해준다.

두번째 input은 기준이 되는 pose를 넣어준다.

  • time shift 데이터를 연결해준다.

세번째 input은 애니메이션 데이터를 넣어준다.

  • unpack된 Agent 데이터를 연결해준다.

약간의 오차는 있지만, 충돌에 사용하는데 큰 무리는 없어보인다.

나쁜 예시) 기준이 되는 포즈를 웅크린 포즈르 잡을 경우, 이런식으로 찢어진 결과를 얻게 된다.

point deform 노드에서도 손등의 튀어나온 부분 등을 잡아주기 위한 parameter가 있다.

Radius 값을 0.1 > 0.5로 올려줬다.
튀어나온 부분이 완화되었다.


이제 dop net 세팅을 진행해보자.

sphere는 어렵게 생각하지 말고, 조각이 많은 집합체(sphere 조각들)로 생각하면 된다.

 

각각의 sphere들은 rigidbody solver에 넣기 위해 assemble 노드를 사용해서 packing 해준다.

 

dop net 을 적용하면 애니메이팅 된 움직임을 보이질 않고 무너진다.

mutant(이었던 것)

a_a_d 세팅이 필요하다.

  • i@active : 시뮬레이션에서 무너져내릴 것이 아니기 때문에 0으로 세팅
  • i@deforming : 시간에 따라 sphere의 위치가 계속 변하기 때문에 1로 세팅

충돌 조건으로 dop net에서 잘 돌아가고 있다.


이제 mutant에 충돌할 물체를 만들어보자.

 

아직 재질에 대해서는 고려하지 않고, 충돌조건이 예쁘게 작동하는지가 오늘의 핵심이기 때문에 충돌할 물체는 간단하게 voronoi fracture 노드를 이용하여 제작한다.

 

너무 폭력적이다.

너무 과한 결과가 나왔다.

box의 하단부에 움직이지 않도록 a_a_d 세팅을 잡아줄 필요가 있다.

아직 과하지만, box가 통째로 날아가진 않는다.
box 조각을 600개로 늘린 결과.

잘 작동'은' 하고 있다.

 

어떻게 하면, 이 충돌의 과함을 잡아줄 수 있을까?

 

일반적으로 지금까지 충돌의 조건을 다룸에 있어서 충격량을 조절해줄 수 있을법한 요소는 '질량'이었다.

 

mutant의 무게에 변화를 줘보자.

mutant density 1의 결과. 별로 낮아진거같지 않다.

생각보다 density의 영향을 받지 않는다.

mutant density 1,000,000의 결과. 1과 별 차이가 없어보인다...?

mass로 변환해서 적용해도 마찬가지이다.

 

 

충돌조건을 만들기 위해 물체(캐릭터)를 sphere로 치환하는 이 방법은 방식 자체는 굉장히 간단하고 편리하지만 결정적인 약점이 존재한다.

  • 바로 힘조절이 사용자가 원하는대로 되질 않는다는 점이다.

 

일반적으로 질량이나 속도를 조절하면서 충격량을 조절해왔지만, 지금의 케이스는 이것이 올바르게 작동하지 않는다.

  • 물론, 날아가는 조각의 속도나 회전에 어떠한 보정을 가해서 보다 약한 힘으로 충돌이 가해진 것처럼 묘사를 할 수는 있지만, 근본적인 해결책은 아니다.
    • 왜냐하면, 충격을 발생시키는 것은 mutant(캐릭터)인데 다른 물체들이 조절의 대상이 된다는 것은 약간 맞지 않는 이야기이다.

 

glue constraint의 strength를 조절해보자.

strength 100

strength 1,000,000

 

mutant가 때리는 힘이 '약해진 것처럼 보인다'.

 

이것으로도 충격에 대한 리액션의 규칙을 정해줄 수 있을지도 모른다.

그런데, 만약 box에 충격을 가할 물체가 mutant 뿐만 아니라 반대편에서 자동차도 이 벽을 때려야했다면? 자동차의 조각의 무게가 상당히 높아져야했을지도 모른다. glue constraint의 strength 값이 저정도로 높은 것은 일반적인 것은 아니니까 말이다.

그리고 벽의 strength 값을 넘기 위해 무게가 올라가는만큼, 자동차의 서스펜션의 힘도 커져야 하고, mutant 캐릭터 하나 때문에 다른 값들을 조절해야할 것들이 굉장히 많아지게 된다.

 

근본적인 문제의 해결은, 캐릭터가 때리는 힘을 사용자가 낮출 수 있어야 한다.

 

한가지 더 아쉬운 점은, 실제 충돌이 일어나는 순간은 팔을 휘두르는 속도가 굉장히 빠르기 때문에 프레임과 프레임 사이에 빈공간이 꽤나 생기게 된다.

  • 프레임과 프레임 사이가 계산이 되지 않았을 수도 있다는 것을 뜻한다.
  • 이 문제를 가장 쉽게 해결하는 방법은 substeps를 늘려주는 것이다.

Substeps 4
Substeps 8

결과는 팔을 휘둘러서 뜯어낸듯한 느낌이 좀 더 예쁘게 표현되지만, 너무 느리다.

 

Substeps의 수치를 높여서 시뮬레이션의 퀄리티를 높이는 것은 정말 최종의 최종의 최종수단이어야한다.

  • 극단적으로 시간의 효율을 포기하는 세팅 방법 중 하나이다.
  • 프레임 사이의 정보를 저장해서 슬로우모션을 표현하려는 것이 아니라면 이 방법은 좀 비효율적이다.

 

substeps의 수치를 변화시키지 않고도, 프레임 사이의 묘사되지 않은 팔의 영향력을 충돌에 올바르게 적용시킬 수 있어야 하고, 다른 물체들에 손을 대지 않고 충돌의 세기를 조절(낮추거나, 높이거나)할 수 있어야한다.


캐릭터의 충돌조건 두번째 방식

 

지금까지의 방식은 물체와 충돌조건을 최대한 일치시켜서 시뮬레이션이 끝나고나면, 충돌조건이 놓인 곳에 고화질 자료를 대체해주는 방식으로 작업을 진행시켜왔다.

 

하지만, 지금의 작업은 결과로써 캐릭터의 움직임이 다 정해진 상태이다.

  • 캐릭터는 충돌을 발생시키는 입장이지 충돌의 영향을 받는 대상이 아니다.

 

  1. 이미 정해진 움직임을 따르는 캐릭터와 같은 경우에는 굳이 충돌조건을 캐릭터에 딱 맞추려고 집착할 필요가 없다.
    • 캐릭터의 움직임에 대한 결과는 이미 정해져있기 때문이다.
  2. 충돌조건이 연속적으로 dop network에 있을 이유 또한 없다.

 

포물선을 그리며 날아가는 sphere와 중간을 가로막고 충돌을 일으킬 조각난 벽의 모습이다.

위에 그려진 기존의 방법은, i@active가 1일 경우 날아가다가 중력의 영향으로 떨어질 수 있으므로, @active는 0으로 세팅을 해주게 되고, sphere의 위치가 이동하기 때문에 i@deforming을 1로 세팅해주는, 위에서 캐릭터를 가지고 작업한 그 방법이다.

단점으로는 생각보다 충격의 힘이 너무 강력했다는 점이다. 그 힘의 세기 또한 정해져있는 상태였기 때문에 충격랑의 조절을 다른 물체를 조절하는 것으로 대신해야 했다. 기본적으로 사용자가 원하는 것은 sphere의 어떠한 값을 조절해서 충격에 대한 힘을 조절해서 벽이 박살나는 정도를 조절하고 싶은 것인데 이 방식은 충격을 가하는 sphere를 주체로 조절할 수 없다는 점이 단점이었다. 

또 하나의 단점으로는 프레임과 프레임 사이의 빈 구간의 존재이다. 위의 그림에서처럼 14 프레임과 15 프레임 사이의 빈 공간으로 인해 sphere가 마치 벽을 때리지 않고 통과한 것처럼 보이게 될 수도 있다.

물론 Substeps의 값을 늘림으로 이 부분을 잡아줄 수는 있지만, 값이 늘어남에 따라 계산시간도 기하급수적으로 늘어나게 된다. 

 

새로운 방식이 필요하다.

(선생님은 이 방식을 fake collision이라고 부르신다고 했다.)

  • 왜 fake collision이냐면, 이 충돌조건은 오직 dop network에서만 존재하고 실제 출력에는 전혀 영향을 주지 않을 데이터이기 때문이다.

핵심은 'sourcing' 이다.

 

일단 시뮬레이션의 시작프레임인 11 frame에 sphere를 i@active가 1인 상태로 등장시킨다. 그러면, 시뮬레이션의 영향을 받고 떨어지게 된다. 대신에 11 frame에 등장한 sphere는 12 frame에 있어야 할 곳으로 던져지게 된다.

 

[등장하고, 딱 한번날아가고, 사라지고] 이 루틴의 반복

 

이 방법의 장점은 i@active가 1이기 때문에 충격의 세기를 질량이나 속도의 조절로 조절이 가능하다는 점이다.

 

 

mutant로 작업을 해보자.

충돌 조건이 필요하기 때문에, 캐릭터의 일부분을 sphere로 채워주도록 하자.

현재 필요한 것은 sphere가 아니고, sphere가 어디에 놓여있는지, point의 위치만 필요하다.

sphere는 dop network 안에서 sourcing을 할 때 copy to points로 붙여주기만 하면 된다.

 

add 노드로 primitive 정보를 날려줬다.

그리고 이 point에 copy to points 를 사용해서 sphere를 붙이면?

우리가 원한 결과가 나오진 않았다.

위의 sphere들의 사이즈를 조절해줄 수 있는 attribute로는 @pscale이 있는데, 이것은 VDB to Spheres의 parameter 항목을 체크해주면 된다.

마지막 단의 Add PScale Attribute에 체크해주자.

@pscale에 의해 각가 다른 사이즈로 sphere가 조절된 것을 볼 수 있는데, 예상과 다르게 sphere가 너무 작다.

우리가 기대했던 사이즈보다 절반이 작다.

 

이것이 의미하는 것은, VDB to Spheres 노드로 만들어진 sphere의 반지름이 copy to points로 붙게 되는 sphere의 지름으로 사용되었다는 것을 의미한다. 즉, @pscale을 두배 키워줘야지 VDB to Sphere의 내용을 copy to points로 복원할 수 있다.

 

이 과정을 dop network 안에서 한다는 의미이다.

 

지금은 point만 남겨서 보도록 하자.

그리고, 각 포인트마다 i@fid를 남겨놓도록 하자.

 

그리고 time shift를 이용해서 31~33 각 프레임마다 손의 위치에 대한 포인트의 위치를 확인해보자.

속도를 구해주는 방법은 목표가 되는 타겟 위치에서 나의 위치를 빼주면 vector가 나오고, 여기에서 구해진 방향, dir에 어떠한 영향을 줘서 v로 쓸 수도 있는것이다.

 

현재의 이 구간은 가장 팔을 빠르게 휘두르고 있는 구간인지라 중간의 비어보이는 부분이 존재한다. 저 빈 구간에 경로를 만들어줄 예정이다.

포물선을 그리면서 경로정보를 남길 수 있도록 작업해보자.

 

지금은 한 프레임 전에 포인트가 있었던 위치를 보여주고 있다.

Trail을 사용해서 궤적을 만들어보자.

add 노드로 fid가 같은 포인트끼리 연결한 모습

이 작업(trail로 위와 같은 정보를 얻어내는 작업)을 진행하는 이유는, '충격에 따른 후속 팔로우를 만들어주고 싶기 때문'이다.

 

움직임이 굉장히 빠른 구간에서는 추가적으로 만들어줘서 trail에 던져주게 되는 sphere들의 충격이 마치 dop network의 Substeps가 프레임-프레임 사이의 정보를 구해주는 것처럼 추가적인 충돌을 만들어내줄 수 있게 된다.

 

후속으로 만들어지는 sphere들은 움직임을 이끄는, 팔에 생성되어 있는 sphere만큼 힘이 강할 필요는 없을 것이다. 

 

dop network에서 trail에 붙은 sphere들이 날아가는 방향은 어떻게 구하게 될까?

  • trail의 각각의 포인트가 어느 방향으로 향하고 있는지를 알아야 할 필요가 있다.

 

쉽게 구할 수 있다.

  • poly frame 노드를 사용해서 tangent U를 구해준다.
  • 혹은 resample 노드도 활용이 가능하다.

방향이 반대이다.
방향전환을 위해 -1을 곱해준다.

후속으로 따라오는 sphere들의 크기가 너무 균일하다.

@pscale에 어떠한 변형을 가하고 싶다.

line을 기준으로 봤을 때, 제일 앞에 있는 팔에 위치한 부분은 1, 멀어질수록 0에 가까워지도록 해서 0~1사이의 값으로 표현이 가능하도록 하고 싶다면, curveu를 사용하면 된다.

 

 

sphere는 dop network 안에 가서 달기로 하고, 정리해준 뒤, dop network 에서 sop 세팅을 해준다.

sphere의 홍수

sphere가 생성되자마자 나이를 먹도록 life count를 추가해준다.

그리고 life count가 1을 넘기면 지워지도록 세팅을 해준다.

 

이제 충격량을 조절하기 위해 휘두르는 팔의 density를 조절해보자.

density 10000
density 1000

 

위에서 만들어줬던 시스템과의 결정적인 차이점이 무엇인가?

위에서는 충격량을 줄이는 것처럼 묘사하기 위해 glue constraint의 strength를 조절해줬었고,

지금은 충격량 조절을 위해 충돌을 일으키는 팔에 대해 직접 힘의 세기(질량, 속도 등)를 조절하고 있는 것이다.

 

충격의 기준이 부숴질 벽이 되어버리면, tweak이 복잡해진다.

 

조각의 비산 또한 눈여겨 볼 부분이다.

아까처럼 통제가 불가능한 그런 조각의 흩어짐은 좋지 않다.

지금의 경우처럼 작은 힘에는 적게 부숴지고, 큰 힘에는 좀 더 크게 부숴지는 것이 맞다.


브루트는 작업중!!!