CVCurveTool로 만든 커브의 위치를 ​​파이썬으로 계산

11768 단어 파이썬maya
maya에서 커브의 특정 위치의 Position 정보를 취하려고하면 control vertex의 Position은 취할 수 있지만 특정 위치의 Position을 취득하는 명령이 없다!
(잘 찾고 있지 않기 때문에 실제로는 커맨드 있을지도 모릅니다만…)
그럼 커브를 1로부터 계산해 Position을 빼내자! 라는 이야기입니다.


소개



maya의 CVCurveTool로 만들어진 커브는 종류로 말하면 B-스플라인 곡선이 됩니다.
wikipedia 에 의하면 B-스플라인 곡선은, 주어진 복수의 제어점과 매듭 벡터로부터 정의되는 매끄러운 곡선이라고 합니다.
복수의 제어점=control vertex이므로 나머지는 매듭 벡터를 알면 계산할 수 있을 것 같습니다.

매듭 벡터란?



매듭 벡터는 제어점이 NURBS 곡선의 어느 부분에 영향을 미치는지 결정하는 매개 변수 값 (매듭)의 열입니다. 매듭 수는 ​​항상 제어점 수 + 곡선 차수 +1과 같습니다.
만일 maya의 디폴트인 채로 곡선의 차수(CurveDegree)를 3, 제어점(control vertex)을 최소로 4로 하면 매듭의 수는 8이 됩니다.


파이썬으로 계산



계산에는 numpy와 scipy를 사용합니다. maya에의 도입 방법은 설명해 주는 사이트가 꽤 있기 때문에 할애합니다.
아래가 코드입니다.
import numpy as np
from scipy import interpolate
import maya.cmds as cmds

ctr = np.array([(0, 0), (1, 1), (2, -1), (3, 1), ])
x = ctr[:, 0]
y = ctr[:, 1]

l = len(x)

t = np.linspace(0, 1, l - 2, endpoint=True)
t = np.append([0, 0, 0], t)
t = np.append(t, [1, 1, 1])

tck = [t, [x, y], 3]

sample = np.linspace(0, 1, (max(l * 2, 70)), endpoint=True)
out = interpolate.splev(sample, tck)
for x, y in zip(out[0], out[1]):
    cmds.spaceLocator()
    cmds.move( x, y, 0 )
    cmds.scale( 0.05,0.05,0.05)
(0, 0), (1, 1), (2, -1), (3, 1) 가 제어점이 됩니다.
그것을 다음 줄에서 x, y로 나눕니다.
ctr = np.array([(0, 0), (1, 1), (2, -1), (3, 1), ])
x = ctr[:, 0]
y = ctr[:, 1]

t는 매듭 벡터가 됩니다.
t의 선두에 [0, 0, 0]과 말미에 [1, 1, 1]에 추가하고 있습니다. 이와 같이 복수의 노트에 대해서, 동일한 값을 주는 것으로 곡선이 제어점 위를 통과하게 되어 커브의 시작점과 종점의 제어점이 일치하게 됩니다.
l = len(x)
t = np.linspace(0, 1, l - 2, endpoint=True)
t = np.append([0, 0, 0], t)
t = np.append(t, [1, 1, 1])

scipy의 splev이라는 함수를 사용하기 때문에 데이터를 정형합니다.
· 매듭 벡터
・제어점(x, y)
· 곡선의 차수
위를 하나로 정리합니다.
tck = [t, [x, y], 3]
sample 는, 어느 정도의 간격으로 Position 를 취득할지의 값이 됩니다. 70곳을 크게 하면 취득할 수 있는 커브가 부드럽게, 작게 하면 바삭바삭해집니다.interpolate.splev(sample, tck) 로 커브를 출력하고 out 에 저장합니다.
sample = np.linspace(0, 1, (max(l * 2, 70)), endpoint=True)
out = interpolate.splev(sample, tck)

계산으로서는 여기까지입니다만 모처럼이므로, maya상에 표시해 보겠습니다.
취득한 Position 곳에 Locator를 배치해 갑니다.
for x, y in zip(out[0], out[1]):
    cmds.spaceLocator()
    cmds.move( x, y, 0 )
    cmds.scale( 0.05,0.05,0.05)

표시되었습니다! maya 커브의 위치와 일치하는 것도 확인할 수있었습니다.


결론



이번은 실험으로서 평면 공간에서 했습니다만, 입체 공간에서도 똑같이 할 수 있을까 생각합니다.
별로 응용이 좋고 느낌은 아니지만, 곡선의 구조를 이해해 두면 여러가지 도움이 되므로 참고가 되면 다행입니다.

좋은 웹페이지 즐겨찾기