닐리 리깅

11.21

닐리의 리깅포인트는 미니스커트다. 로폴이었다면 대충 다리에 붙였을 것 같은데, 표현이 정밀해질수록 할 일이 많아진다.

첫시도는 실패. 구상은 좋았던 것 같은데, 생각보다 예쁜 모양이 나오지는 않았다.

이것도 실패

이것도 실패

이건 쓸만하다. 하지만 디테일잡기가 조금 어렵다.

스케일 + 드라이빙. 이게 가장 좋은 것 같다! 좀 더 자세히 파 보자.

러프한 구현.

본은 예상했던 대로 돌아가는데, 생각보다 완전하지 않다. 일단, 회전값이 예상대로 안들어온다. 다리의 첫번째 트위스트본은 다리를 바깥쪽으로 돌리면 완전히 90도 비틀리는데, x+z가 항상 90도라고 생각했던 것이 오판이었다.

그래서 이렇게 비스듬한 각도에서는 계산이 제대로 되지 않는다.

드라이버의 코드는 이렇다.

clamp(1 + 
(pi/2/sperate_count * offset_level + z) * (0.8/(pi/2/sperate_count)) + 
(pi/2/sperate_count * offset_level - x) * (0.8/(pi/2/sperate_count))
,0.2,1)

11.23

오늘의 깨달음. 오일러 회전방식이 애니메이션 뿐만 아니라 현재 상태에도 영향을 끼친다. 수잔의 XYZ축을 모두 45도로 설정한 후 각기 오일러 회전방식을 다르게 해주었더니 결과가 다르게 나왔다.

각방으로 연구를 해보았으나, 결국 완전한 방법은 깨닫지 못했다. 쿼터니온은 사람이 못알아듣는 값이고 결국 오일러값을 조절해야 하는데 이 값이 왜 이렇게 들어가는지 이해하지 못했다. 아득한 수준너머의 일이라고 생각하고 그냥 괜찮은 오일러값을 고르는데 집중해야 할 것 같다.

11.24

트위스트 본의 첫번째 본은 다리를 옆으로 뻗었을 때 분명 x축으로 90도가 돌아간다. 이는 앞으로 뻗었을 때와 옆으로 뻗었을 때의, 그리고 그 중간 보간과정에서 어느 축으로든 회전각의 합이 90도가 된다.라는 계산에서 시작한 작업이었지만, 실제로는 오일러 계산에 의해 선형적으로 보간되지 않는다.

하지만 그렇다 해도… 강제로 90도로 맞춰주면 되는 것 아닐까? 비율적으로는 z에서 x로 각의 비중을 넘겨줄 때 그 값이 비선형적이라 해도 어쨌거나 90도에 맞추어 재계산해주면 되는 것 아닐까? 싶어서 다시 스크립트를 짜려고 보니… 이제는 이 많은 내용을 한 줄에 표현하기가 불가능하다. 함수가 필요하다.

https://docs.blender.org/manual/en/dev/animation/drivers/workflow_examples.html#driver-namespace

뜻이 있는 곳에 길이 있다고 했나! 드라이버엔 커스텀 함수를 포함할 수 있다. 네임스페이스 안에 함수를 포함시켜 사용하면 된다고 써 있다. 이제 지금까지 한 줄로 썼던 표현식을 함수화 시킬 수 있다.

def skirt_scaler(z, x, front, side, back, level):
    hpi = pi/2
    scale_front = (hpi/front*level+z) * (0.8/(hpi/front))
    scale_back = (hpi/back*level-z) * (0.8/(hpi/back))
    scale_side = (hpi/side*level-x) * (0.8/(hpi/side))
    
    z_scale = min(0, min(scale_front, scale_back))    
    x_scale = min(0, scale_side)
    result = 1 + z_scale + x_scale
    
    result = max(0.2, result)
    result = min(1, result)
    
    return result

그러니까… 이걸 한 줄에 쓰고 있었다. 어휴. 스크립트 표현식에서 편의상 제공하는 clamp는 정규블렌더 스크립트에선 사용할 수 없다. 어쩐지 math네임스페이스에도 없다. min/max로 짤라야 한다.

이제 여기서 z,x의 값을 비율 보간해 보자.

def skirt_scaler(z, x, front, side, back, level):
    hpi = pi/2    
    zx = abs(z)+abs(x)    
    extra = max(0, zx-hpi)
    z_sub = extra*(z/zx)
    x_sub = extra*(x/zx)
    
    scale_front = (hpi/front*level+z-z_sub) * (0.8/(hpi/front))
    scale_back = (hpi/back*level-z+z_sub) * (0.8/(hpi/back))
    scale_side = (hpi/side*level-x-x_sub) * (0.8/(hpi/side))
    
    z_scale = min(0, min(scale_front, scale_back))        
    x_scale = min(0, scale_side)
    
    result = 1 + z_scale + x_scale
    
    result = max(0.2, result)
    result = min(1, result)
    
    return result

망… 더 많이 파묻힌다…그렇게 쉬운 일이 아닌가보다.

하지만 어쨌거나 스크립트 표현식을 함수화할 수 있는 방법은 알아냈다.

이렇게 쓰던 걸

이렇게 깔끔하게 쓸 수 있다!

단점은 파일을 열 때마다 스크립트를 한 번 실행해주어야 한다는 것이다. 이것마저 귀찮다면 제작이 끝나고 애드온에 함수를 내장시켜놓으면 될 것이다.

하지만….

문제는 여기서 끝나지 않았다. 이번엔 본이 커튼처럼 뼈가 있는 부분외의 부분들에 볼륨이 나타나는 문제가 나타났다.

분명 이것은 본의 가닥이 많아지면 해결이 되는 문제이긴 하다. 하지만 그럼에도 완전히 해결되지는 않는다.

그렇다면 윤곽을 유지하기 위해 보더모양의 본을 설치하고 지금까지 만들었던 줄기본을 헬퍼로 쓰는것은 어떨까

러프한 구현결과…어? 괜찮을 듯? 보더에 단계를 둔다면?

훨씬 나은 결과!

게다가 가닥본들은 이제 헬퍼본들이기 때문에 엔진으로 넘기지 않아도 된다는 장점도 있다.

오늘의 깨달음.

드라이버는 본이 지워져도 캐시에 남아있다. 때문에 같은 이름의 본을 추가하면 드라이버가 그대로 전승된다. 이는 본의 제약조건을 복사할 때 매우 효과적인데, 드라이버가 지워질 것이 무서워서 symmetry를 사용하지 않고 일일이 수기로 복사해주는 번거로움을 줄여준다. 물론 캐시가 날아가면 못쓰므로 파일을 다시 열기 전에 작업을 끝내도록 하자.

버텍스 웨이트 툴에서 copy는 가장 나중에 선택한 점의 값을 기선택한 점에게 복사해주는 것이다. 스무스를 주지 못하는 웨이트를 잡아야 하는 특성상 옆의 값을 따와야 하는데, 이럴 때 좋다.

마침내, 기본은 거의 된 것처럼 보인다.

닐리 리깅”의 4개의 생각

  1. 리깅이라는거이 정말 쉬운게 아니군요.
    단순하게 tv용 애니메이션을 만든다- 라고 하면 저런 함수가 들어갈 일은 없는거죠?
    게임 속에서 다양한 상황 속에서 자연스럽게 움직이려고 하는 상황이기에 필요한 과정인거고

    1. TV용 애니를 만들어본 적이 없어서 잘 모르겠어요. 전 드라이브를 블렌더에서 만났지만, 마야에도 스크립트가 있겠죠…?! 하지만 늘 일정에 쫓긴다고 들었으니, 이처럼 느긋하게 스크립트로 치마나 들추고 있진 않을 것 같긴 합니다.

      1. 친구들이 TV용 애니메이션 애니메이터인데, 리깅 해서 온것 외적으론 죄다 수작업이라고 하더라구요.
        박스 더미 같은것에 뭔가 충돌해서 산산히 흩어지는 것도 시뮬레이션과 수작업을 병행한다고 했었으니…
        딴것보다 아동용이라 저런 좋은 치마는 안나올것 같습니다.
        악당들도 시원하게 줘패고 싶고 로봇에서 톱날도 나와서 적 로봇 절단도 내고 싶은데, 그런거 못하는게 스트레스라나요!

      2. 음 사실 뭐 저도 하면서 뭔 짓인가 싶습니다. 백수니까 해보는 짓이랄까… 회사에선 못하겠지요. 지금 스커트본으로만 4일쯤 날려보낸 것 같은데…

댓글 남기기