RBD workflow
준비 단계
Type 단위로 나눈 후 비슷한 방식으로 하나하나 진행
- 시뮬레이션 영역을 Geometry로 정하여 simArea와 non-simArea로 나누기 위해 boolean fracture를 한다
(이 단계에서 for-each connected pieces와 compile block을 연계 활용하여 시간 단축)
- simArea를 분리하여 main fracutre작업 (이후 모든 for-each는 그냥 compile block을 덛씌우기, foreach end에 Multithread when compiled 체크)
- fracture가 완성되면 필요에 따라 proxy piece들에게 cluster지정 (rbd cluster SOP, 타입은 group constraints로)
- 현실적인 모션을 위해 mass어트리뷰트를 이 지점에서 계산한다. 밑에 개똥철학 세부설명 별첨
- 이러면 proxy와 원본의 name수는 일치하고, cluster값을 가진 constraints까지 해서 rbd 시뮬레이션의 삼신기가 완성된다
각 타입들을 하나하나 rbd pack하지말고 original, proxy, constraints들을 하나하나 참조하여 merge한 후 모든 type들을 합친 것들을 rbd pack하여 cache로 보내자. 이 과정에서 name의 문자열과 cluster의 값의 중복을 특별히 유의해야함.
시뮬레이션 전단계
시뮬레이션 버튼 누르기 전에
- rbdpackedobejct노드의 Physical 탭 - compute mass를 체크해제한다. 안그러면 값이 override됨
- 필요에 따라 노드를 열고 들어가서 기본 active값을 0으로 바꾼다
- 폭파의 경우 웬만하면 inherit velocity로 작업하지 말고 post-solve에 SOP solver를 만들어서 작업하자. 동적인 제어도 가능하고 훨씬 왔다갔다 하기 편함
- pop drag를 만들고 대략 0.1의 값에 ignore mass를 체크해제한 후 vex expression을 통해 종단속도를 정해주자. 안그러면 질량이 가벼운 물체들은 공중에서 거의 멈춰버리게 됨
이렇게 해둔 후 tv채널의 값을 예를 들어 0.25로 설정하면, 속도가 0.25미만으로 내려간 piece들은 더이상 항력을 받지 않고 일정한 속도로 낙하함. 이것도 더 파고 들어가려면 상수가 아니라 mass에 따라서 정할 수도 있겠다.
- Constraint는 relationship탭에서 Attach internal...을 체크하고 후디니에서 만들어준 Constraint Sop Solver를 Post-solve인풋에 끼워넣고 작업하자. Compile셋업을 해줘서인지 매우 빠르다.
폭파, constraint삭제, 작은 조각으로 흩어진 cluster piece들에 대한 mass값 감소, 공기저항 등을 모두 DOP내부에서 해결했는데, 기본 rbd 작업에서 사용하지 않았던 개념들을 쭉 한 번 사용해보았고 결과는 대만족이었다. 컨스트레인트와 rbd piece들간 어트리뷰트를 주고받을 땐 이럴 필요까지 있나 생각했지만, 일단 가능하고 할 줄 아는게 중요한 거니까..
post-sim은 작업하며 시도해본 내용들 추가할 예정
아직 pre-solve와 post-solve의 개념이 모호한데 이것도 추가 예정
[mass 어트리뷰트]
mass를 왜 써야하는가? (정말 간단히 후디니 관점으로)
F = ma, 뉴턴 제2법칙에 의해 질량이 작은 물체는
1. drag force(항력)을 많이 받는다. (무거운 돌덩어리보다 가벼운 나뭇잎이 겉보기에 공기저항을 더 많이 타는 것과 비슷)
2. 가속도가 크다. (같은 힘으로 밀어도 무거운 돌덩어리보다 가벼운 debris가 더 큰 가속을 받는 것과 비슷)
1번은 pop drag의 ignore mass를 끔으로서 달성할 수 있고, 2번은 velocity에 mass를 기반으로 만든 마스크를 생성해서 눈속임할 수 있다. (무거운 물체의 velocity스케일을 줄이고 반대로 가벼운 물체는 스케일을 올리는 방식으로, 이러면 똑같은 v값을 모든 piece들에 곱해도 사실상 다른 값들이 들어가니까 훨씬 직관적이고 편하다.)
즉, 정확한 mass를 가지고 있으면 굳이 복잡하게 parameter값을 바꾸고 velocity에 노이즈를 줄 필요가 없어서 편리하다.
@v = dir(방향) * dist_mult(거리 마스크) * n_mass(질량 마스크) * random(진짜 순수하게 0.7-1까지 랜덤)
이러면 그냥 의미없는 노이즈 찾기가 아닌, 실제 물리력을 기반으로 v값을 정했기 때문에 모션이 굉장히 그럴싸해진다
한편, mass값을 SOP단계에서 계산하지 않아도 rbd packed object노드에서 기본적으로 mass를 계산해주지만, 디폴트 값은 문제점이 크게 2가지 있음
1. cluster를 constraints로 묶은 이상 뭉텅이로 된 piece들의 값이 정확하지 않음
- 실제 color어트리뷰트로 확인을 해보면 반은 맞고 반은 틀린 느낌이다. (대충 10%만 틀려도 쓸까말까인데 무려 반이나)
2. 깨진 cluster에 대한 mass덜어내기가 불가능함.
- 이게 가장 주된 원인인게, 엄청난 cluster뭉텅이로 들어온 piece가 산산조각이 나면 질량 또한 줄어 들어야한다. 하지만 dop 내부에서 이것을 동적으로 수정하지 않으면 쪼끄만 piece가 엄청난 질량을 가진 상태로 drag값을 무시할 것이다. 무슨 자유낙하도 아닌데 이것은 물리적으로 말이 안됨. 따라서 초기값을 정하고 끝내면 안된다.
때문에 cluster단위로 for-each를 돌려서 (detach가 있다면 @cluster<=0, @cluster>0 두 그룹으로 나눠야함)
1. mesure SOP을 name단위로 계산하여 area값을 구함 (unpack되어 있어야함)
2. assemble을 하여 area를 tranfer시키고, point(혹은 primitive)의 수를 구함
3. area는 detail로 promote시켜서 합을 구한다음 다시 prim어트리뷰트로 바꾼다
4. 계산 결과를 cluster piece들에게 옮겨온다
(먼지가 아니면 mass 1이하의 값들은 remap하여 적어도 1 이상은 되게 변경)
이렇게하면 비교적 정확한 mass어트리뷰트를 얻을 수 있다. 당연히 많은 name으로 묶인 cluster가 큰 mass값을 가지고 있을 것 (이 중에서 같이 묶인 name piece들의 개수값을 constraint에도 attribute copy시켜준다)
이런 식으로 constraint solver에서 1-(cluster에서 떨어져 나간 piece의 수/전체 cluster원래 수)를 해서 백분율을 만들고, mass에 곱셈해주면 떨어져 나갈 때마다 mass가 감소한다. 물론 사실 cluster가 산산조각 난 시점에서 이미 바닥에 박혀있거나 더이상 육안으로 drag를 확인하기 어려울 수도 있지만, 못하는 것과 안하는 것은 크게 다르기 때문에 시도는 해보았다. 사실 필요 이상으로 복잡해서 안 쓸 것 같..
더 자세히 적고 싶은데 글로 적는 건 한계가 있으니 까먹으면 그냥 힙파일 열어봐야겠다