본문 바로가기

Houdini/Houdini1_Rigidbody

RIGID BODY_15 리깅 시뮬레이션 BASIC - Ep15_Part04. 자동차 서스펜션 시스템


지난 시간에 이어서 충돌조건을 만들어보자.


현재 상황에서 충돌에 활용되는 부분은 바퀴와 밑면의 proxy 데이터 부분이다.

이 상황에서
이렇게만 충돌처리에 사용되고 있다.

그래서 충돌이 발생할 경우, 바퀴까지 먹어 들어가서 자동차가 파고드는 상황이 발생한다.

 

실제 바디의 사이즈에 맞게 충돌조건을 더 만들어줄 필요가 있다.

실제 바디에 그냥 convex hull을 적용하게 되면 바퀴와 겹치는 부분이 발생해서 충돌처리를 함에 있어서 바퀴가 구르지 않게 된다.

 

충돌조건을 만들기 위한 아이디어

자동차의 original body를 쪼갠다.

이런식으로

 

이 중에서 바퀴에 영향을 줄 수 있는 조각과 아닌 조각을 구분해 준다.

 

바퀴 쪽에 영향을 줄 수 있는 조각들을 날려준다.

body를 대체하는 proxy box에 영향을 줄 수 있기에 아래의 가운데쪽 조각도 날려줬다.

이제 남은 조각들은 glue constraint로 연결해 줄 것이다.

  • 절대 떨어지지 않도록 glue constraint로 연결해줄 것이다.

 

glue constraint를 적용해 줄 수 있도록 각각의 조각들을 연결해 준다.

  • 주의할 점은 cap만 연결해서는 dop network에 들어갔을 때 아래의 바퀴 쪽과 따로 놀기 때문에, 연결된 cap 덩어리는 아래의 바퀴 - 바디 부분과도 연결을 해줘야 한다.

cap 조각 묶음은 시뮬레이션에서는 사용되지만, 출력에서는 사용되지 않는다.

 

핵심이 되는 부분은,

  1. cap 조각들을 어떻게 끊기지 않도록 연결해 주느냐
  2. cap 조각 덩어리를 어떻게 body에 연결해 주느냐

이 작업이 끝나면 서스펜션 작업은 상대적으로 쉽다.

 


body를 조각내는 방법은 무엇이 있을까?

 

일단 점을 기준으로 물체를 조각내는 voronoi fracture를 알고 있다.

하지만 이번에는 boolean fracture를 사용해 볼 것이다.

boolean fracture를 적용하기 전, original body 데이터를 하나의 polygon으로 만들어줄 필요가 있다.

  • volume으로 만들어서 SDF를 구해주고, 다시 polygon으로 변환해 주면 된다.
  • 19 버전(혹은 그 이후)은 위와 동일한 기능을 해주는 remeshgrid 노드를 사용하면 된다.

 

Boolean Fracture Node

  • 조각을 나눠주는 기준은 '면'이다.(voronoi fracture는 '점')
  • 바로 결과가 보이진 않지만, exploded view 노드를 연결해 보면 조각난 것을 확인할 수 있다.

면을 묶어주고 조각내줄수도 있다.

 

우리가 현재 조각을 내는 이유가 무엇인가?

body가 가지는 충돌조건과 바퀴가 가지는 충돌조건이 cap이 제공할 충돌조건과 겹치지 않도록 하기 위해 조각을 내서 불필요한 조각을 날려주려는 것이다.

 

조각을 내는 것은 boolean fracture가 해줄 것이고, 조건으로는 grid로 만들어주면 된다.

이제 assemble 노드로 packing 해준 뒤, 불필요한 조각을 날려버리자.

이 조각들은 결과출력이 아닌 시뮬레이션에서만 사용될 것이기 때문에 폴리곤이 많을 필요는 없다. proxy를 낮은 용량으로 줄여주기 위해서(용량이 줄어들면 시뮬레이션 시간도 절약된다.) 각 조각들을 convex hull로 덮어준다.

 

더 용량을 줄이겠다면, poly reduce로 면을 줄여서 용량을 더 작게 만들어줄 수도 있다.

테스트를 위해서 dop network를 만들고, s@name도 만들어주자.

이쁘게 잘 뽀샤진다.

위의 조각들이 이제 충돌의 조건으로 사용될 것이다.


이제 위에서 만들어준 조각들이 딱딱하게 고정될 수 있도록 constraint 세팅을 만들어줘야 한다.

여기에서부터 시작~!

primitive 정보를 add 노드를 사용해서 날려주면, 각 조각들의 위치정보와 @name이 담긴 포인트만 남게 된다.

이제 저 포인트들을 연결해 주면 된다.

일단 예시로 두 개의 포인트, 그리고 그 포인트와 이름이 같은 프리미티브 두 개를 떼어내 보자.

만약, 우리가 통제 가능한 포인트의 수량이라면, 직접 묶어서 constraint 세팅을 만들어줄 수 있다.

이때 사용할 constraint는 딱 '붙이고'싶은 것이기에 glue constraint를 사용하면 될 것이고, 어떠한 충격에도 떨어지지 않게 하기 위해서 strength를 '-1'로 설정해 주면 된다.

 

하지만 문제는, 조각의 수가 너무 많다는 점이다.

수동으로 잡는데 무리가 있다.

 

그리고 이전 강의에서 만들었던, 닿아있는 두 물체 사이의 연결관계를 자동으로 구해주는 시스템이 있지만, 만능은 아니다. 닿아있지 않더라도 억지로 고정을 해줘야 하는 경우도 존재하기 때문에 다른 방법을 알고 있어야 할 필요가 있다.

 

이번에 사용해 볼 노드는 connect adjacent pieces 노드이다.

Connect Adjacent Pieces Node

  • 가까운 포인트들을 선으로 연결시켜 주는 노드
  • Search Radius : 연결시키려는 한계 반경
    • 제공하는 모든 포인트에 대해서 0.1(search radius) 반경 안에 포인트가 있다면, 포인트들끼리 연결해서 선으로 만들어내게 된다.
    • 각 점에서 원을 그리게 되고, 반경이 서로 겹치게 될 경우, 선이 생기는 것이다.
      • 점 A와 점 B의 반경이 겹칠 때, 점 A와 점 B를 연결하는 선이 생긴다.

두 점을 이어주는 선의 길이는 0.713872 이다.
이 선이 생겨난 노드의 parameter이다.

 

  • Max Search Points : 반경 안에 연결해 주려는 최대 포인트 개수
    • 만약 반경 안에 100개 이상의 포인트가 존재한다면, 최대 100개까지만 선으로 만들어주게 된다.
    • '자기 자신을 포함해서' 포인트 개수를 count 한다.
      • max search points가 1일 경우, 자기 자신을 포함해서 가장 가까운 포인트는 자기 자신이기 때문에 만들어지는 선은 없다.

search radius 10 / max search points 2의 결과

  • Length Attribute : 활성화해 줄 경우 어트리뷰트로 선의 길이를 저장해 줄 수 있다.
  • Connection Type : 연결시켜 주려는 타입을 선택하는 항목이다.
    • point를 연결해 줄 것이기 때문에 Adjacent Points(인접한 점들)를 선택해 준다.

search radius 0.36이 되니 두 점을 연결하는 선이 생겼다.

이제 떼어낸 점이 아닌, cap에 대한 점들에 적용해 보자.

search radius 0.36 / 반경이 더 넓어야할 것 같다.

이 선들은 어떠한 정보를 가지고 있을까?

라인을 선택해서 떼어내 준 뒤 정보를 확인해 보자.

point 정보
primitive 정보

constraint 세팅을 위한 정보가 잘 들어가 있다.

불필요한(중복되는) 연결들을 날려준 결과이다.

현재 restlength는 이미 구해졌기 때문에, constraint type과 constraint name만 정해주면 된다.

  • 딱딱하게 붙일 것(위치와 회전 모두 고정)이기 때문에 type은 "all"로 적용한다.

glue constraint는 충격의 허용량을 넘어서면 연결이 끊어져버린다.

지면에 부딪힌 cap, 잘 보면 앞쪽 후드의 연결이 끊어져서 빨간 선이 사라진 것을 확인할 수 있다.
strength의 설명, -1이면 never break. never다.

strength -1의 결과, 내동댕이 쳐도 연결이 끊어지지 않는다.

만들고자 했던 cap은 다 만들었다.


이제 원래 작업했던 dop network에 cap 데이터를 넣어보자.

멋지게 터졌다.

현재 constraint 세팅을 불러오지 않은 상태이다. constraint 세팅도 불러오자.

 

하지만 이것도 올바르게 시뮬레이션되지는 않는다.

cap과 body를 고정해 줄 필요가 있다.

 

body와 cap을 연결해 주기 위해서 필요한 조각으로는 proxy_body(box)와 cap의 어떠한 조각일 것이다.

  • 연결을 위해 cap에서 조각을 골라줘야 한다.

가운데에 cap과 body를 잇는 glue constraint 연결 관계선이 생겼다.

충돌조건이 잘 만들어져서 파고드는 것이 사라졌다.


서스펜션을 만들어보자.

 

지금까지의 작업은 다음과 같다.

가장 먼저, 바퀴와 바디를 만들었다.

이것만으로는 충돌조건이 부족하기 때문에 따로 cap을 만들어줬다.

  • 현재 이 캡은 충돌에도 연결이 끊어지지 않도록 고정되어 있는 상태이다.
  • 그리고 캡은 body와도 완전히 고정되어 있다.

서스펜션 세팅에 대해 방법은 다양하다. 정답 또한 딱 하나만 있는 것도 아니다.

 

서스펜션 세팅은 실제 자동차처럼 만들어줄 수도 있다. 하지만 복잡해지면 복잡해질수록 불안정해지는 경우가 많다. 특히 hard constraint를 사용할 때 문제가 발생한다. (예를 들어, 위치를 hard로 고정해 주더라도 강한 충격에 의해 옆으로 밀려나는 그런 문제들)

 

서스펜션에 대한 아이디어.

  • 바퀴 쪽에 스프링과 같은 충격흡수장치가 존재하고,
  • 그 위에 차체가 올라가 있다.

 

proxy body와 사이즈가 같은 box를 만들어서 위로 올려주고, soft constraint로 이 box와 proxy_box를 연결해 준다.

 

그리고, 위에서 만들어준 cap을 위의 box에 연결해 주도록 한다.

추가적으로 하얀색 box가 새로 만들어져야 하고, 하얀 box와 proxy_body box를 연결해 줄 constraint 가 필요하다. 마지막으로 cap과 proxy box를 연결했던 constraint를 하얀 box와의 연결로 바꿔주면 된다.


각각의 모서리에 대해 constraint 서스펜션을 만들어줘야 한다.

서스펜션이 잘 만들어졌으면, 이제 서스펜션 제작으로 사용된 box와 cap을 연결해줘야 한다.

위의 proxy_body 연결을 sus 연결로 바꿨다.

시뮬레이션은 잘 되는 듯 하나, 고화질로 치환을 해주니 문제가 생긴다.

서스펜션이 제대로 먹히질 않는다.

현재 고화질로 치환되는 조건은 @name이 body 인 두 물체를 치환해 주는 것이기 때문에 이 부분에 대해 조작이 필요하다.

 

@name이 body인 것과 sus인 것을 따로 떼어낸다.

그리고 body는 출력에서는 사용할 필요가 없기 때문에 날려주고, sus의 @name을 body로 교체한 뒤, 데이터들을 다시 묶어주고 transform pieces에 넣어준다.


이번에는 옆으로 미끄러지는 것, 드리프트 한번 묘사해 보자.

 

드리프트가 발생할 때의 접지력, 즉 타이어의 마찰력을 생각해 볼 필요가 있다.

만약 앞바퀴와 뒷바퀴의 마찰력이 다르다면?

 

차량의 옆으로 힘이 가해질 때, 앞바퀴의 마찰력이 뒷바퀴보다 더 클 경우, 앞바퀴 쪽의 마찰력에 의해 힘이 상쇄되면서 상대적으로 뒷바퀴보다 덜 미끄러지게 된다. 차가 돈다는 이야기이다.

 

이 부분에서 각각 마찰력에 대해 앞바퀴와 뒷바퀴가 다르도록 정의해주자.


정리.

  1. Rigid body가 무엇인지 배웠다.
  2. Sourcing에 대해 배웠다.
    • Sourcing의 이유 - 다양한 물체를 원활하게 다루기 위해서
  3. Constraint를 배웠다.
    • constraint의 합성 및 기본적인 리깅까지 진행했다.

 

다음 시간부터는 조건에 따른 constraint의 변화에 대해 공부해 보자.


다른 차도 적용해보려고 했는데 cap 조각이 이상하게 적용된다!!!!

이것도 시스템화... 하려면 할 수도 있을 거 같다는 생각이 머릿속을 간질간질...

 

근데 조각으로 나눌 때 사이드미러의 경우는 나누기가 어렵겠지...? 싶은데 어찌어찌 어설프게나마 될 것 같기도 하고...

 

주말 동안 procedural modeling, 그리고 unreal engine에 적용하는 것에 대해 좀 찾아보려고 한다.

 

정답은 하나가 아니다. 그래서 후디니가 너무 좋다. :)