Skip to content

머리카락은 촉수처럼 변하는 게 아니라 흔들려야 합니다 ​

글: Oleg Sidorkin, Cinevva CTO 겸 공동 창업자

왼쪽에는 이전 모션, 오른쪽에는 개선된 모션을 적용한 소녀의 레이어드 헤어를 나란히 비교한 모습.

캐릭터가 고개를 돌립니다. 머리카락은 잠시 뒤따라 움직이고, 살짝 흔들린 다음 가라앉아야 합니다. 하지만 첫 번째 버전은 다르게 움직였습니다. 헤어스타일이 촉수로 변하려는 것처럼 끝부분이 아래로 말려 들어갔습니다.

본 길이는 유지됐습니다. 시뮬레이션도 안정적이었습니다. 확인하던 수치도 모두 기준을 통과했습니다. 하지만 움직임은 여전히 잘못되어 보였습니다.

이 글은 자동 리거에 관한 다음 이야기입니다. 머리카락에 자체 조인트와 보조 모션을 부여하는 과정입니다. 단순한 테스트 메시로 시작한 뒤 실제 아바타 두 개로 옮겨 갔습니다. 그 결과 구현 방식과 측정 항목이 모두 달라졌습니다.

먼저 실제 포니테일 다시 만들기 ​

Seed-san에는 별도의 포니테일 메시가 있습니다. 이번 테스트에서는 해당 메시의 원래 스킨 웨이트를 지우고 머리에 부착한 다음, 기하학적 피터가 6개 조인트로 이루어진 새 헤어 체인을 만들도록 했습니다. 캐릭터의 나머지 부분은 기존 스키닝을 유지했습니다. 짧은 앞머리 체인 7개도 아티스트가 제작한 웨이트를 그대로 유지했습니다.

피터는 연결된 머리카락 표면을 루트에서 바깥쪽으로 따라가며 해당 경로에 조인트를 배치하고, 인접 조인트의 영향을 블렌딩합니다. 부착 지점의 좁은 띠 영역은 고정됩니다. 이는 선택한 헤어 다발을 처리하는 워크플로입니다. 어떤 메시가 머리카락인지 직접 지정해야 하며, 임의의 캐릭터에서 모든 가닥을 자동으로 찾아내지는 않습니다.

아래에서 포니테일을 직접 시험해 보세요. 헤어 모션을 사용하면 하나의 미리보기에서 이전 솔버와 개선된 솔버를 전환할 수 있습니다. 머리카락이 가라앉는 모습을 보려면 움직인 뒤 가라앉기를 선택하세요. 일시 정지하여 포즈를 살펴보거나 미리보기를 드래그해 시점을 회전할 수 있습니다. 애니메이션 선택기에서는 260개의 유니버설 애니메이션을 모두 제공합니다. 클립을 선택해 전신이 움직이는 모습을 확인할 수 있으며, 프레이밍 → 머리카락 클로즈업을 선택하면 카메라가 다시 머리카락을 비춥니다. 고개 돌리기 테스트를 선택하면 통제된 비교로 돌아갑니다.

Open this demo in a full window ↗

포니테일이 가려지지 않도록 이 화면에서는 Seed-san의 별도 백팩과 로봇 팔을 숨겼습니다. 이 가시성 변경은 몸, 머리카락 형상, 스킨 웨이트 및 애니메이션에 영향을 주지 않으며, 백팩 충돌을 수정한 것도 아닙니다.

유니버설 애니메이션 라이브러리 사용해 보기 ​

애니메이션 선택기는 Cinevva의 리거 및 런타임과 동일한 월드 공간 리타기터를 사용합니다. 각 아바타의 VRM 휴머노이드 메타데이터를 리타기터가 요구하는 조인트 이름에 매핑하고, 이전의 헤어 전용 스킨이 아니라 바디 스킨을 선택하며, 헤어 시연이 시작되기 전에 애니메이션이 적용되지 않은 몸의 포즈를 캡처합니다. 이렇게 하면 다른 클립을 선택했을 때 돌아간 머리나 웅크린 자세가 캐릭터의 기본 포즈로 취급되는 일을 방지할 수 있습니다.

선택한 클립은 공유 유니버설 라이브러리에서 가져와 한 번 리타기팅한 뒤 선택한 캐릭터에서 재생됩니다. 캐릭터가 화면 안에 머물도록 수평 이동은 제거합니다. 이 데모에서는 원래 일회성으로 지정된 동작을 포함해 선택한 모든 유니버설 애니메이션이 반복 재생됩니다. 다시 시작을 누르면 선택한 동작이 처음부터 재생됩니다. 헤어 모션은 바디 애니메이션 이후에 실행됩니다.

각 아바타에서 260개 클립을 모두 리타기팅했습니다. 총 520개의 결과물에서 필수 바디 조인트 누락, 잘못된 숫자 트랙, 헤어 조인트를 대상으로 하는 바디 애니메이션 트랙은 발견되지 않았습니다. 또한 Idle, Walk, Jump, Back Flip, Dance, Crouch Forward 및 Sitting Idle을 샘플링하여 몸의 움직임과 동기화를 확인하고 렌더링된 포즈를 살펴봤습니다. 이 검사는 두 리그에서 리타기팅을 사용할 수 있음을 보여주지만, 모든 프레임의 시각적 완성도를 보장하지는 않습니다. 리타기팅 검사 결과.

의상에도 제작 시 설정된 제어 장치가 필요합니다. 이 VRM 샘플은 소매와 팔다리 변형에 에임 및 트위스트 제약 조건을 사용합니다. 휴머노이드 조인트만 애니메이션하면 소매가 원래 포즈에 남게 됩니다. 이제 데모는 공식 VRM 노드 제약 조건 모듈을 사용해 이러한 제어 장치를 불러오고, 바디 애니메이션 이후이자 헤어 시뮬레이션 이전에 업데이트합니다. 이는 제공된 의상 리그를 보존하는 것이며 천 시뮬레이션을 추가하는 것은 아닙니다.

전체 라이브러리를 직접 살펴볼 수 있지만, 아래의 클리핑 및 늘어남 측정에는 여전히 통제된 고개 돌리기 시퀀스를 사용합니다. 따라서 모든 춤, 낙하 또는 공중제비 동작에서 머리카락이 충돌하지 않는다는 것을 입증하지는 않습니다.

문제는 기본 형태에 있었습니다 ​

조인트 체인에는 되돌아갈 방향이 필요합니다. 이전 솔버는 이미 구부러진 상위 조인트를 기준으로 그 방향을 계산했습니다. 따라서 위쪽의 작은 편향이 다음 세그먼트의 기본 방향을 바꾸고, 이것이 다시 그다음 세그먼트의 방향을 바꿨습니다.

이러한 누적 때문에 말림이 발생했습니다. 각 본의 길이를 올바르게 유지하는 것만으로는 이를 막을 수 없었습니다.

새 솔버는 움직이는 머리의 좌표계 안에서 헤어스타일의 원래 곡선을 기억합니다. 각 세그먼트에는 여전히 관성과 감쇠가 적용되지만, 복원 방향은 원래 형태에서 가져옵니다. 머리가 돌아갈 때 머리카락이 뒤처질 수는 있지만, 그 지연이 아래쪽 전체의 새로운 기본 곡선으로 변하지는 않습니다.

기존 아티스트 리그도 조금 더 단단하게 조정하고 감쇠를 높였습니다. 개선 전후 비교에는 좌표계 변경뿐 아니라 이러한 튜닝도 포함됩니다.

원래 곡선을 유지하는 움직이는 목표점 ​

세그먼트 i에서 현재 조인트 위치를 oi, 원래 자식 오프셋을 ai라고 하겠습니다. 세그먼트가 되돌아가려는 위치는 다음과 같습니다.

ri=oi+RHRi0(sai).

RH는 체인 부착 프레임, 일반적으로 머리의 애니메이션 회전입니다. Ri0는 해당 프레임에서 이 세그먼트까지 누적된 원래 회전이며, s는 모델 스케일입니다. 조인트 위치는 체인을 따라가지만 목표 방향은 저장된 곡선에서 가져옵니다. 이 방향에 이미 구부러진 부모의 회전을 사용했던 것이 말림을 누적시킨 원인이었습니다.

각 단계에서는 이 목표점을 향한 인력과 중력 및 지수 감쇠를 결합합니다.

ui=e−ch[vi+hfi],fi=k(ri−xi)+g,yi=xi+hui.

여기서 xi는 시뮬레이션된 끝점, vi는 그 속도, k는 복원 계수, c는 감쇠율, g는 솔버가 사용하는 중력 가속도입니다. 데모는 h=1/120초 간격으로 바디 모션과 머리카락을 함께 샘플링합니다. 이는 질량을 암묵적으로 1로 가정한 커스텀 스프링 업데이트이며, 완전한 탄성 로드 또는 XPBD 솔버는 아닙니다.

그런 다음 끝점을 조인트로부터의 고정 거리 Li=s‖ai‖로 되돌립니다.

x^i=oi+Liyi−oi‖yi−oi‖.

이 투영은 본 길이를 보존합니다. 하지만 이것만으로 모든 삼각형 모서리를 보존하거나 머리카락 가닥을 의상 바깥에 유지할 수는 없습니다. 구현에서는 후보 방향이 퇴화하는 경우 기본 방향을 사용합니다.

이제 전체 헤어스타일 시험해 보기 ​

두 번째 아바타인 pixiv 샘플에는 12개의 헤어 체인과 12,868개의 헤어 버텍스가 있습니다. 여기서는 아티스트가 제작한 조인트와 웨이트를 유지하고 보조 모션 동작만 교체합니다. 이 예시는 기존 헤어스타일의 애니메이션을 보여주는 것이며, 결합된 헤어 메시를 자동으로 재구성하는 예시는 아닙니다.

Open this demo in a full window ↗

옆과 뒤에서 끝부분을 살펴보세요. 개선된 버전은 움직임을 유지하면서 의도한 실루엣을 더 잘 보존합니다. 이전 버전에서는 끝부분이 모여 더 뚜렷하게 말립니다.

실제 모델에서는 눈에 잘 띄지 않는 다른 버그도 드러났습니다. 일부 짧은 앞머리는 스킨 본이 아닌 노드에서 끝납니다. 이전에는 이러한 체인을 건너뛰었습니다. 이제 임포터는 이런 끝점을 허용하고 VRM 1 스프링 메타데이터에서 명시적으로 이름이 지정된 헤드 헤어 체인을 읽습니다. 또한 구 및 캡슐 충돌 프록시와 조인트별 충돌 반지름도 읽습니다.

VRM의 스프링 본 사양은 교환 구조를 제공합니다. 우리의 모션은 모든 VRM 스프링 설정을 완전히 구현한 것이 아니라, 기본값을 튜닝한 커스텀 솔버입니다. 데모는 제작된 셰이딩, 텍스처, 얼굴 및 의상 외곽선을 표현하기 위해 pixiv의 MToon 머티리얼 로더를 사용합니다. 확장된 헤어 외곽선 셸은 얇은 레이어 표면과 교차하므로 비활성화했습니다. 두 모션 설정은 동일한 조명과 머티리얼을 사용합니다. pixiv의 three-vrm 스프링 본 구현은 해당 생태계에서 널리 인정받는 참고 구현입니다.

앞쪽 머리카락이 셔츠를 통과한 이유 ​

조인트 위치만 확인하면 눈에 보이는 한 가지 문제를 놓칠 수 있었습니다. 두 조인트가 모두 충돌 형상 바깥에 있더라도 조인트 사이의 가닥이 어깨를 통과할 수 있었습니다. VRM 반지름 처리에서 인덱싱 오류도 발견했습니다. 다음 조인트의 반지름을 읽는 바람에 마지막 세그먼트의 반지름이 0이 되었습니다.

이제 두 앞쪽 머리카락은 각 세그먼트 전체에 걸쳐 충돌 검사를 수행합니다. 공유 피팅 패스는 기존 충돌 형상 주변에서 보이는 몸과 의상 형상을 측정하며, 몸 크기를 기준으로 확장 한도를 설정합니다. 가닥의 도달 범위, 위치 및 스킨 웨이트 소유권을 사용해 세그먼트 검사가 필요한 체인을 식별합니다. 이제 두 아바타 모두 모델 이름이나 가닥 이름에 관한 규칙 없이 이 알고리즘을 사용합니다. 전체 헤어스타일로 충돌 검사를 확장하자 늘어남이 증가했기 때문에 머리 부착 제약 조건과 짧은 앞머리는 기존 처리 방식을 유지합니다.

프록시와는 별개로 실제 스키닝된 셔츠를 기준으로 결과를 검사했습니다. 고개 돌리기 한 주기 동안 이전 모션에서는 셔츠가 앞쪽 머리카락 버텍스 1,503개 중 최대 555개를 가렸습니다. 자동 피팅에서는 초당 30프레임과 120프레임 모두에서 1mm 측정 임계값을 넘는 충돌이 0건이었습니다. 이전 방식에서 측정된 최대 깊이는 75.2mm였습니다. 이는 정면 시점의 가림 측정이며, 완벽한 표면 충돌이나 모든 애니메이션에서의 충돌 방지를 보장하지는 않습니다. 앞쪽 머리카락 측정값 다운로드.

앞쪽 머리카락을 셔츠 바깥에 유지하는 데에는 상충 관계가 있습니다. 레이어드 헤어스타일의 99백분위수 늘어남은 충돌 피팅 전 17.1%에서 18.0%로 증가했습니다. 그래도 이전 솔버의 26.0%보다는 낮으며, 아래 표에는 현재 결과가 반영되어 있습니다.

접촉 반응에는 별도의 수정이 필요했습니다. 머리카락 가닥을 의상 바깥으로 밀어낸 위치 보정이 속도로 변환되어 다음 단계에서 눈에 띄게 튕겼습니다. 이제 겹침을 해소할 때 해당 임펄스를 추가하지 않고, 접촉 지점으로 들어가는 움직임을 제거하며, 미끄러지는 움직임은 유지합니다. 정지 상태 가닥 회귀 테스트에서는 끝점 접촉과 전체 세그먼트 접촉을 모두 검사합니다. 수정된 가닥은 튕겨 나가지 않고 접촉 위치에 머뭅니다.

반발 임펄스 없이 가닥 전체에서 접촉 처리하기 ​

헤어 링크와 캡슐 축은 모두 선분입니다. 각 점을 p(u)와 q(v)로 나타내고, u,v∈[0,1]이라고 하겠습니다. 두 선분 사이의 여유 거리는 다음과 같습니다.

d=minu,v∈[0,1]‖p(u)−q(v)‖,C=d−(rb+rh).

rb는 바디 프록시 반지름이고 rh는 헤어 충돌 반지름이며, 둘 다 월드 단위입니다. C가 음수이면 겹침을 의미합니다. 자식 끝점만 검사하면 u=1로 고정되어 긴 머리카락 중간의 충돌을 놓칠 수 있습니다. 세그먼트 접촉 검사는 전체 구간을 탐색합니다. 구는 캡슐 축의 길이가 0인 특수한 경우입니다.

위치 보정이 반발로 변하는 것을 막기 위해 끝점을 접촉 밖으로 밀어내기 전에 속도를 재구성합니다.

vi∗=x^i−xih.

0이 아닌 접촉 보정이 적용된 후, n을 해당 보정 방향의 정규화된 벡터라고 하겠습니다. 이 보정 방향으로 들어가는 성분만 제거합니다.

vi+=vi∗−min(0,vi∗⋅n)n.

접선 방향 움직임은 유지되므로 가닥이 미끄러질 수 있습니다. 위치 보정 자체는 속도에 추가되지 않습니다. 이후 솔버는 접촉 투영을 반복하고 링크의 반지름 방향 속도를 제거합니다. 상호작용하는 제약 조건으로 인해 겹침이 일부 남을 수는 있습니다.

Back Flip에서는 다시 만든 포니테일의 또 다른 적용 범위 문제가 드러났습니다. 별도의 헤어 스킨에 몸통 본이 포함되어 있지 않았습니다. 이제 콜라이더 탐색은 바디 계층 구조를 검색하며, 몸통 영역이 빠진 경우 공유 피터가 몸통 캡슐을 추가합니다. 초당 30프레임과 120프레임에서 각각 6초 동안 Back Flip을 검사한 결과, 샘플링된 포니테일 링크가 해당 캡슐을 관통한 사례는 없었습니다. 이는 프록시 충돌 검사이며 모든 의상 삼각형에 대한 충돌 방지를 보장하지는 않습니다. 기존 고개 돌리기 변형 검사도 계속 통과합니다.

빠른 움직임에는 포즈 사이의 검사도 필요합니다. 이제 데모는 바디, 의상 제약 조건 및 머리카락을 초당 120단계로 함께 진행하고, 각 단계 사이에서 움직이는 구 및 캡슐 프록시를 기준으로 가닥을 검사합니다. 접촉 시 전체 가닥을 멈추는 대신 측면 미끄러짐을 유지합니다. 그렇지 않으면 머리카락이 달라붙는 현상이 발생했습니다. 두 아바타의 Walk 및 Back Flip은 4초 검사에서 초당 30, 60, 120프레임 모두 동일한 샘플링 헤어 위치와 속도를 보였습니다. 이 방식은 샘플링된 기본 도형의 움직임을 처리하지만 모든 의상 삼각형에 대한 연속 충돌 검출은 아니며, 추가 제약 조건으로 인해 해결되지 않은 접촉이 남을 수 있습니다. 프레임 속도 및 접촉 검사 다운로드. 그 일관성에는 대가가 따릅니다. 앞서 초당 60프레임으로 진행한 2개 뷰 벤치마크에서 기록된 95백분위수 업데이트 시간은 렌더링을 제외하고 Seed-san이 약 1ms, 레이어드 모델이 14~23ms였습니다. 이 비용은 캐릭터 2개를 기준으로 하지만, 현재 라이브 데모는 캐릭터 1개를 렌더링합니다. 레이어드 모델은 여전히 최적화가 필요하며, 이 데스크톱 측정 결과만으로는 휴대폰 성능을 판단할 수 없습니다.

피팅 도구는 여전히 해부학적 가정과 제한된 확장을 사용합니다. 필요한 신체 역할이나 지오메트리가 없으면 제작자가 설정한 값을 유지하고, 지원되지 않는 변환을 보고합니다. 이름이 변경된 본, 스케일 변경, 의상 두께, 숨겨진 액세서리, 원래 설정 복원을 다루는 검사 8개도 추가했습니다. 이 두 아바타는 튜닝에 사용되었습니다. 결과를 일반적으로 신뢰할 수 있다고 말하려면 아직 보지 못한 헤어스타일과 의상을 추가로 테스트해야 합니다.

스켈레톤뿐만 아니라 메시도 측정하기 ​

본의 길이는 그대로여도 주변의 삼각형은 늘어날 수 있습니다. 따라서 12초 동안 실행하면서 모든 헤어 삼각형의 변을 측정했습니다. 처음 4초는 머리를 움직이고, 이어지는 8초는 움직임이 가라앉도록 했습니다. 시뮬레이션은 초당 120스텝으로 실행되며, 메시 측정값은 초당 30회 샘플링합니다.

각 변에 대해 실행 중 발생한 최대 늘어남을 기록합니다. 표에는 이러한 변별 최댓값의 99백분위수가 나와 있습니다. 즉, 변의 99%가 해당 값 이하로 늘어났습니다.

원래 길이가 ℓe0인 메시 변 e=(a,b)에 대해 스키닝된 버텍스 위치 za(t)와 zb(t)를 측정합니다.

ρe(t)=‖za(t)−zb(t)‖ℓe0,me=maxt∈Tρe(t).

T에는 샘플링된 프레임이 포함됩니다. 보고되는 백분율은 100(Q0.99({me})−1)이며, 여기서 Q0.99는 전체 변의 99백분위수입니다. 백분위수를 구하기 전에 각 변의 최댓값을 취하면 시간 평균에 가려질 수 있는 짧은 늘어남도 보존됩니다. 최악의 변 수치는 대신 maxeme를 사용하므로, 심하게 변형된 작은 영역도 보고서에 그대로 드러납니다.

실제 모델 테스트이전 모션개선된 모션
Seed-san: 재구성한 포니테일과 원래 앞머리8.0%5.0%
Seed-san: 원래 헤어 리그7.6%5.1%
pixiv: 원래 레이어드 헤어 리그26.0%18.0%

가장 많이 늘어난 개별 변도 여전히 중요합니다. 레이어드 모델에서는 102.7%에서 70.8% 늘어남으로 개선되었지만, 이는 백분위수에 가려져서는 안 되는 남아 있는 결함입니다. Seed-san에서 가장 많이 늘어난 변은 두 경우 모두 35.2%에서 27.8%로 개선되었습니다. 이는 튜닝에 사용한 개발 예제의 측정값이며, 아직 보지 못한 헤어스타일에서의 성공률이 아닙니다.

체인 루트는 고정된 상태로 유지되었습니다. 마지막 2초 동안 샘플링된 프레임 사이에서 측정한 끝점 이동량은 개선된 모든 경우에 0.001mm 미만이었습니다. 리깅, 고정된 루트, 형태 보존, 충돌, 짧은 끝점, 임포트, 애니메이션 소유권을 다루는 집중 테스트 13개도 마련했습니다. 또한 뷰어에서 리그를 적용하고 되돌리는 작업과 루프 애니메이션 및 일회성 애니메이션 내보내기도 확인했습니다.

측정 데이터 다운로드. 라이브 예제는 프로토타입의 뷰어 및 내보내기 경로와 동일한 솔버 코드를 사용합니다. 사전 녹화된 영상이 아니라 상호작용할 수 있는 렌더링입니다.

이 기술로 가능한 것과 아직 해결하지 못한 것 ​

분리된 포니테일이나 머리카락 한 가닥의 경우, 이제 선택한 지오메트리에서 조인트, 웨이트, 보조 모션까지 생성하는 경로가 마련되었습니다. 기존에 호환되는 헤어 리그가 있다면 아티스트의 작업을 유지하면서 애니메이션을 적용할 수 있습니다. 애니메이션에 해당 헤어 조인트의 트랙이 이미 포함되어 있으면, 절차적 솔버는 그 위에 두 번째 움직임을 더하지 않고 제작된 모션에 제어권을 넘깁니다.

수치 기반 헤어 벤치마크는 머리 회전과 부드러운 몸 이동을 사용합니다. Universal 선택기를 통해 다른 동작도 살펴볼 수 있지만, 이러한 측정만으로는 달리기, 점프, 구르기 중의 헤어 품질을 입증할 수 없습니다. 충돌 프록시는 전체 신체 표면 충돌을 대신하지 못하며, 아직 머리카락 간의 자체 충돌도 해결하지 않습니다. 땋은 머리, 곱슬머리, 서로 붙어 있는 헤어 영역, 실제 휴대폰 성능은 각각 별도의 테스트가 필요합니다.

이 기능은 아직 실험 단계입니다. 하지만 실제 캐릭터를 검사하면서 개선 효과를 구체적으로 확인할 수 있었습니다. 이제 머리카락은 되돌아가야 할 형태를 계속 다시 쓰지 않고도 움직일 수 있습니다.


모델 크레딧. Seed-san © VirtualCast, Inc. — 공식 VRM 샘플 모음 제공. VRM1_Constraint_Twist_Sample © 2022 pixiv Inc. — three-vrm 예제 모델 제공. 두 파일 모두 재배포와 수정을 허용하는 VRM Public License 1.0 메타데이터를 포함합니다. 재구성한 포니테일과 커스텀 모션은 저희가 변경한 부분입니다. 소스 URL 및 파일 해시에서 사용한 정확한 샘플을 확인할 수 있습니다.

애니메이션 크레딧. Universal 클립은 Quaternius가 제작했으며, Universal Animation Library와 Universal Animation Library 2에서 가져왔습니다. CC0으로 제공됩니다.

다음 단계: 생성된 캐릭터에 재사용 가능한 헤어 적용하기 ​

후속 실험은 리깅되지 않은 라이브러리 메시에서 시작합니다. 46가지 헤어스타일을 개구리에 맞추고 추출된 스트랜드 가이드를 살펴보세요. 라이브 실험에서는 두피 부착과 앞으로 구현할 물리 시뮬레이션을 분리합니다.