트위터


2017/03/16 02:08

후디니 Houdini Vex vex

==원문서 : CGwiki
==짬짬이 번역해보는중


Wrangle Sops는 작은의 Vex 코드를 작성하고 사용하기에 빠르고 효율적으로하기 위한 몇 가지 UI가 잘 갖춰져 있습니다. 그들은 다양한 특징 (포인트, 프림, 디테일, 속성) 들이 '모두 같은' 메뉴에 포인트/프림/디테일 로 전환된 것들입니다.

Wrangle nodes에 접근하는 가장 좋은 방법은, 40x40 그리드를 생성후, point wrangle을 붙여 주는 것으로 시작됩니다.



Contents

1 Create a new attribute
2 Get existing attribute values
3 Implicit vs explicit attribute type
4 Create UI controls
5 Customise the UI elements
6 Common functions
7 Built-in attributes
8 Example: Random delete points by threshold
9 Example: Wave deformer
10 Attributes vs variables
11 Example: Rotation
11.1 Rotate a single point with sin and cos
11.2 Rotate geometry with sin and cos
11.3 Rotate into a twirl or spiral
11.4 Rotate with a matrix
11.5 Rotate prims around an edge
11.6 Rotate prims around an edge, alternate version
12 Wrangles vs hscript vs vops vs everything else
13 Mixing vex and vops with snippets
14 Get values from other points, other geo
15 Blurring attributes with vex and point clouds
16 Get attributes from other inputs
17 Arrays
18 Search an array with find
19 Access group names procedurally in vex
20 Solver sop and wrangles for simulation
21 Solver and wrangle for branching structures
22 Get transform of objects with optransform
23 optransform to do a motion control style camera
24 More on rotation: Orient, Quaternions, Matricies, Offsets, stuff
25 ZOMG more rotation: Convert N to Orient with dihedral
26 Convert N and Up to Orient with maketransform
27 Remove points that don't have normals directly along an axis
28 Scaling with vex and matrices
29 xyzdist to get info about the closest prim to a position
30 Rubiks cube
31 Vex vs Vops
32 Vex snippet cheat sheet
33 Further learning





-[ 1 Create a new attribute ]-

새로운 플롯 속성의 'foo' 를 정의하고 싶다면, 그냥 입력하세요

@foo;

ctrl+Enter 키를 눌러서 geometry Spreadsheet를 보면서 하면 새롭게 foo 속성이 생긴 것을 볼 수 있습니다.
이 @ 는 후디니에게 '이것을 속성으로 해달라' 는 것을 알려주며, 기본적으로는 float(플롯) 유형으로 입력됩니다.

initialized를 하고 싶나요?

@foo=1;

벡터 속성이 필요한가요? '@' 앞에 'v' 를 추가하는 것으로 가능합니다. intialise 하려면, 중괄호 안에 숫자를 넣거나, 함수나 다른 속성으로 뭔가 하고 싶다면 'set()' 을 사용하세요.

v@myvector = {1, 0, 3};
v@other = set(0, @P.x, 1);

'v' 와 같이, 적절한 접두사를 사용하여 속성 유형을 설정할 수 있습니다.

// common ones 주로 쓰는 것들
f@foo = 12.234; // float 플롯
i@foo = 5; // int 인티저
v@myvector={1,0,3}; // vector 벡터

// less common ones그외 기타
p@george;  // quaternion, a 4 value vector 사원수 혹은 4벡터
3@transform; // a 3x3 matrix 3-3행렬
 
// there's more, see below. :) 나머지는 아래를 참고하세요 :)

이곳에 전체 리스트가 있습니다





-[ 2 Get existing attribute values ]-

myvector 속성이 각 포인트들의 위치값으로 가져오길 원한다면

v@myvector = @P;

@라는 기호는 속성을 가져와 설정하는 것에 주로 사용됩니다.
지오메트리 스프레드 시트에 표시되는 모든 속성은 이름 앞에 @를 붙임으로써 엑세스(접근/불러오기)할 수 있습니다.

만약 각 포인트에 있는 N의 1.5배를 원한다면
(기본 그리드에서는 스프레드 시트에 N이 숨어있습니다. 씬 뷰에서는 Display Normal 을 켜는 것으로 시각화 할 수 있음)

v@myvector = @N * 1.5;

벡터 또는 색상의 개별 속성에 엑세스하려면, @attribute.channel 을 사용합니다.
예를 들어 각 점의 y 값을 구하여 반으로 나눕니다.

@foo = @P.y / 2;

비슷한 방법으로, 각 점의 컬러 Red채널을 X위치의 2배인 sin으로 설정하려면

@Cd.r = sin( @P.x * 2 );

Cd 또는 P 와 같은 벡터 속성을 사용하려면 여러가지 방법으로 구성요소를 참조 할 수 있으므로 편리하게 사용할 수 있습니다.
구성요소는 r, g, b / x, y, z / [0], [1], [2] 가 가장 많이 사용됩니다.

// These all do the same thing, set the first component of the vector:
// 이것들은 모두 같은 역할을 합니다. 벡터의 첫 번째 요소를 설정합니다.
@Cd.r = 1;
@Cd.x = 1;
@Cd[0] = 1;

// As are these, all setting the third component:
// 물론 이것들은 모두 세번째 요소를 설정합니다.
@P.z = 6;
@P.b = 6;
@P[2] = 6;





-[ 3 Implicit vs explicit attribute type ]-

Wrangles 은 특정 공통 속성들의(@P, @Cd, @N, @v, @orient) 유형(Float,Vector,Integer등)을 따로 지정하지 않아도 됩니다만,
본인이 따로 만든 속성이 있다면, 달리 지정하지 않는한 앞서 말한 기본인 플롯으로 간주합니다.

후디니가 생각한대로 작동하게 하기 위해선 그 유형을 앞에 붙여줘야 합니다. 예를들어 @mycolur를 벡터로 설정한 다음, 이를 회전목마에 사용하려고 합니다.

// BAD
@Cd = @mycolour; // This will treat it as a float and only read the first value (ie, just the red channel of @mycolour)
// 이렇게 되면 float으로 간주되어 첫번째 값만 읽게됩니다 (즉, @mycolour의 red 채널만입니다. RGB)
 
// GOOD
@Cd = v@mycolour; // Explicitly tells the wrangle that its a vector.
// wrangle의 대상인 벡터를 정확히 명시해뒀습니다

모든 작업을 마친 뒤, 이러한 유형을 지정해 주지 않아 문제가 발생 할 수 있습니다.
잊지마세요. 자신이 만든 속성값 앞의 유형을 확실히 지정해주세요.





-[ 4 Create UI controls ]-

먼저 이렇게 해줍시다.

@Cd.r = sin( @P.x * 5 );

하지만 여기서 5 를 다른 번호로 변경하려고 합니다. 다른 번호로 코드를 계속 변경하거나 5 를 ch('scale') 로 바꿀 수 있습니다.

@Cd.r = sin(  @P.x * ch('scale')  );

ch() 는 후디니가 UI 구성요소(보통 슬라이더입니다)를 호출하는 채널을 찾도록 지시합니다.
텍스트 편집기의 오른쪽에 있는 작은 플러그 아이콘을 누르면 후디니가 vex 코드를 스캔하고, 아직 존재하지 않는 채널을 참조했다는 것을 알게됩니다. 그리고선 Wrangle 의 하단에 'scale' 이라는 채널이 만들어지고 이 슬라이더를 조절함으로써 색상이 업데이트 되는 구조입니다.

사용할 수 있는 몇가지 채널 유형이 있습니다. ch() 및 chf() 는 모두 float 채널을 만듭니다. 그 외에도

// An int channel
// INT 유형의 채널
i@myint = chi('myint');
 
// A vector channel
// Vector 유형의 채널
v@myvector = chv('awesome');
 
// A ramp channel
// 램프 유형의 채널
f@foo = chramp('myramp',@P.x);


마지막의 램프 유형은 정말 편리합니다.
먼저 하나의 값(@P.x)들을 모두 읽어들인 뒤, UI 램프 위젯을 통해 다시 매핑한 다음 @foo 를 통해 피드값을 가져옵니다.
나는 결국 내 설정을 통해 이들 중 많은 것을 사용하게 됩니다. 들어오는 값이 0부터 1까지의 범위에 있다고 가정할 때, 램프로 공급하기 전에 값을 맞춰야 합니다. 이땐 fit 함수가 적합합니다 작성방법은 if(value, oldmin, oldmax, newmin, newmax) 입니다.
예를들어 X를 -0.5와 6 사이로 다시 매핑한 다음 램프를 사용하여 해당값을 적색 채널에 공급해보겠습니다.

float tmp = fit(@P.x, -0.5,6,0,1);
@Cd.r = chramp('myramp',tmp);

(**)호기심으로 fit함수를 사용하지 않고 바로 넣어봤습니다. @P.x 가 전체적으로 -5부터 5까지 분포되어 있고, 램프를 0에서 1까지 단순히 증가하는 그래프로 지정한 상태로 스프레드시트를 봤을때, [0 to 5], [0 to -5] 로 나뉘어서 0 이 0으로, 5와 -5가 1 로 변환되었습니다. 이 원인이 무엇인지는 저도 잘 모르겠습니다.


자, 이제 Ui슬라이더에 기존 값의 시작점과 끝점까지 정의합시다.

float min = ch('min');
float max = ch('max');
float tmp = fit(@P.x, min,max,0,1);
@Cd = 0;  // lazy way to reset the colour to black before the next step 다음과정을 준비하기 위한 검정색만들기 과정.
@Cd.r = chramp('myramp',tmp);






-[ 5 Customise the UI elements ]-

플러그 버튼은 편리한 기능이며 모든 채널 값들을 검색하고, 기본값들과 함께 기본 유형을 만듭니다.
일단 채널이 만들어지면 Wranlge 노드에서 우클릭하여 'edit parameter interface'(혹은 우측상단 톱니바퀴 메뉴의 parameter panel)에 들어가서 플롯의 범위나 기본값, 레이블 등을 원하는대로 변경할 수 있습니다.

이중에서 보통 기본적인 벡터 채널을 컬러채널로 변환하는게 많이 쓰입니다.
한번 해봅시다. vex에서 필요한 만큼 많은 벡터 채널을 만들었습니다. 예를들어,

v@colour1 = chv('col1');
v@colour2 = chv('col2');
v@colour3 = chv('col3');
v@colour4 = chv('col4');

그런 뒤 플러그 버튼을 클릭, 톱니바퀴의 edit the parameter interface 에 들어가서, shift-select로 만들었던 4개를 모두 선택하고, type을 'color' 로 변경합니다. 그 다음 민감한 변화를 최소화 하기 위해 show color as 를 HSV slider로 변경해주세요. 이게 제일 다루기 편합니다.






-[ 6 Common functions ]-

이외에도 wrangle로 vex를 사용할 때 99%로 나오는 것들입니다.

fit()
최대와 최소값 사이의 숫자들을 받아들어, 다른 2개의 값 (보통 0부터 1까지로) 을 넣으세요.
예를들어 -5에서 20까지의 @u 를 0에서 1로 다시 매핑하고 싶을땐
foo = fit(@u, -5, 20, 0, 1);

rand()
0과 1사이의 임의의 숫자를 생성합니다. 일반적으로 포인트 ID를 제공하므로, 각 포인트는 임의의 숫자를 얻습니다.
foo = rand(@ptnum);

sin() , cos()
사인과 코사인입니다. 다만 radian 안에서.

radians()
각도에서 라디안으로 숫자를 변환합니다
foo = radians(90);

length()
벡터의 길이를 측정합니다. 예를들어 원점에서 한 점까지의 거리를 측정할 때
dist = length(@P);

distance()
두 점 사이의 거리를 측정합니다.
dist = distance(@P, v@mypoint);






-[ 7 Built-in attributes ]-

사용할 수 있는 변수가 몇가지 있습니다. 가장 쉽게 볼 수 있는 방법은 point vop을 만들어서 global params를 보는 것입니다.
다음은 일반적인 것들입니다.

@ptnum : 포인트 id
@numpt : 총 포인트 수
@Time : 현재 시간 (초)
@Frame : 현재 프레임
@primnum : 프리미티브 ID
@numprim : 총 프리미티브 수






-[ 8 Example: Random delete points by threshold ]-

Matte Ebb 씨께서 이것을 보여준 뒤로 나는 이것을 하루에 수백만번 사용하고 있습니다. Scatter의 일부 point들에 아래의 wrangle을 함께 사용합니다.

if ( rand(@ptnum) > ch('threshold') ) {
   removepoint(0,@ptnum);
}

이제 플러그 버튼을 눌리고 새로 생긴 threshold 의 슬라이더를 움직이면, 슬라이더의 0 과 1 사이에서 무작위로 포인트들이 사라지는 것을 볼 수 있을 것입니다.

rand(@ptnum)
// 각 점은 ID를 기반으로 0과 1사이의 무작위 난수를 얻습니다.

> ch('threshold')
// 만들어진 난수를 threshold(뜻:임계) 값의 슬라이더와 비교하여 임계값 보다 큰 경우..

removepoint(0,@ptnum)
// 포인트를 삭제합니다. 여기서 0은 input1 을 의미합니다. 즉, 이 wranlge 에 연결된 모든 모든것을 말하며, @ptnum은 포인트를 대상으로 삼을 참조값입니다.






-[ 9 Example: Wave deformer ]-

먼저 40x40의 그리드를 준비합니다.
중심에서 방사되는 동심원 Sin파동을 만들겠습니다. 즉, 각 점의 원점까지의 거리를 측정해야 합니다.

@d = length(@P);

그리고 그것들을 sin()으로 보내고, 이를 이용해 각 점의 Y위치를 직접 설정합니다.

@P.y = sin(@d);

하지만 여기서는 이를 슬라이더로 사용하도록 만들겠습니다.

@P.y = sin(@d * ch('scale'));

플러그버튼을 눌린 뒤 슬라이더를 직접 조작해보세요. (값이 1을 넘도록 조작해보세요)
슬라이더를 움직일때마다 파도가 움직일 것입니다.
이제 파도가 애니메이션 되도록 time값을 추가합니다.

@P.y = sin(@d * ch('scale') + @Time);

다만 우리는 파도를 밖으로 보낼것이기 때문에 시간은 반대로 줍시다.

@P.y = sin(@d * ch('scale') - @Time);

이제 속도를 조절하기 위한 슬라이더도 추가합시다.

@P.y = sin(@d * ch('scale') + (ch('speed') * @Time) );

지저분하네요. 잠시 정리를 하겠습니다.
Wranlges 에서 좋은점은 가독성을 위해 여러 줄로 나눌 수 있다는 것입니다.

@d = length(@P); // 'd' 속성은 현위치에서 0점까지의 거리값으로 생성됩니다
@d *= ch('scale'); // 'd' 속성은 슬라이더(name:scale)값을 곱하여 생성됩니다
@speed = -@Time*ch('speed'); // 'speed' 속성은 슬라이더(name:speed)값에 시간을 곱하여 생성됩니다
@P.y = sin(@d+@speed); // y위치는 d 속성과 speed 속성을 더한값의 Sin 값으로 생성됩니다

여기에 몇가지 더 더해봅시다. 최대높이와 거리에 따른 감쇠값을 만들겠습니다.
최대 높이는 간단합니다. 최종 결과가 무엇이든 채널값을 참고삼아 추가로 값을 곱해버리면 됩니다.
물론 1을 곱하면 바뀌지않을것이고, 0을 곱하면 높이는 없어지겠죠. 다른숫자도 적절하게 조절됩니다.

@P.y *= ch('height');

마지막으로 감쇠값을 제어하는 Ramp입니다. Ramp는 0과 1사이의 변수값을 가져오도록 하기 위해 우선 만들어진 ramp 값을 참고하여 fit()을 사용해 0과 1사이로 다시 매핑합니다.

@falloff = fit(@d, ch('start'), ch('end'), 1, 0);
// falloff 속성은 'd' 값을 최대값 start 와 최소값 end 를 최대 1과 최소 0사이로 다시 매핑한 값입니다

램프채널에는 이름과 변수가 필요하며, 변수는 램프의 곡선을 통해 다시 매핑됩니다. 이 결과를 P에 직접 곱합니다.

@P.y *= chramp('falloff', @falloff);
// y위치값은 falloff를 참조삼아 만들어진 Ramp채널(name: falloff) 을 곱한값으로 만들어집니다

여기서 약간 사소한 문제는, 시작과 끝이 전체의 공간(월드 스페이스) 단위가 될 것으로 예상했지만, 예상외로 'end' 가 커졌습니다.
우리가 이미 파동의 횟수를 제어하기 위해 Scale 채널을 d 에 곱해버렸기 때문에 된 것 같습니다.
아래는 이를 개편한 수정판입니다.

@d = length(@P); // d는 현위치에서 0점까지의 거리값
@speed = @Time * ch('speed'); // speed 는 시간에 채널'speed'를 곱한 값
@falloff = fit(@d, ch('start'), ch('end'),1,0); // falloff 는 d의 최대(start)와 최소(end)를 1과 0으로 매핑한 값
 
@P.y = sin(@d*ch('scale')+@speed); // y위치는 d와 채널'scale' 와 speed 를 모두 더한 값의 sin 값
@P.y *= ch('height'); // y위치는 여기서 채널'height'를 곱한 값
@P.y *= chramp('falloff', @falloff); // y위치는 여기서 falloff값의 참조로 만들어진 램프채널'falloff' 을 곱한 값






-[ 10 Attributes vs variables ]-

앞서 주어진 예제는 모두 @ 구문을 사용하여 포인트의 속성을 가져오거나 설정했습니다. 
만약 wralnge이 많지 않거나, wranlge 밖에서는 속성을 필요로 하지 않는다거나,
지오메트리 시트가 지저분해지는게 싫다거나, 모든 포인트의 데이터들이 메모리를 차지할 수 있습니다.
특히 복잡한 장면일 경우엔 더더욱이요.

이를 대신해 wrangle 내에서만 존재하는 변수를 만들 수 있습니다.
구문은 다른 C-style의 언어와 유사합니다.
전반적인 단어로 유형을 정의하되, 변수 앞에는 아무것도 붙이지 않습니다.

float foo;
vector bar = {0,0,0};
matrix m;

foo = 8;
bar.x += foo;

포인트 변수와 vex 변수는 각각 별개로 분리되어 있기 때문에 각각 동일한 이름으로 설정할 수 있으며,
이들은 상호 공존할 수도 있게 됩니다. 
의미하지 않았던 곳을 쉽게 추가하거나 필요로 하는 곳에 하나를 쉽게 제거할 수 있게 됩니다.

float dist = length(@P);
// 이 wrangle 내에서만 존재하는 로컬 변수

@dist = dist
// 새로운 point 속성 @dist를 생성하고, 로컬변수 'dist' 를 할당합니다.

변수를 사용하는 예제활용을 위해 앞의 예제를 다시 작성해보겠습니다.
물론 이번엔 변수를 선언하는 일을 먼저 합니다.

float d;
float speed;
float falloff;

d = length(@P);
speed = @time * ch('speed');
falloff = fit(d, ch('start'), ch('end'), 1, 0);

@P.y = sin(d*ch('scale')+speed);
@P.y *= ch('height');
@P.y *= chramp('falloff', falloff);






-[ 11 Example: Rotation ]-



2016/12/31 23:59

프롤로그 - (Update 20150304) 메인카테고리



닉네임 . Dsharp [D#, 디샵]

직업. 대학생

할줄 아는것. 숨쉬기

모자란것. 숨쉬기 (?!)


능력없는 한 학생이 넷상에서 개인자료 관리하고 주변 네티즌들과 소통하기 위해 생성된 이글루스의 한 이용자의 블로그입니다.
일단 나름 영상관련쪽으로 배우고는 있는데, 하라는 연습은 안하고 머릿속 자작영상에 대한 스토리 망상만 가득한 놈입니다.
생각만 해야지해야지. 몸은 어그적어그적. 이러면 안되는걸 알면서도 어그적어그적.

아래는 기본 스팩입니다.

 나름 규칙적인 생활중.
 일단 학생이다보니 평일 기상시간과 취침시간은 거의 비슷한 편.
 문제라면 취침시간이 되게 늦는데 그 원인은 컴퓨터와 스마트폰.

 다섯가지 항마력을 지니고 있음.
 하지만 그다지 전문적이진 않은 일상계 잡덕
 

 살짝 감성적 (이라 쓰고 남들보기 쓸데없는 눈물이 많다고 해석) 임.
 애니로 봤을 때 제일 많이 울었던 것은 "클라나드"
 영화로 봤을 때 제일 많이 울었던 것은 "각설탕"
 (이게 지금 몇년째 바뀌지 않고 있다..)

 장난기가 꽤 있음.
 오프라인상에서도 사람 낚는걸 즐김.
 물론 어느정도 수위는 지켜가면서.
 그래도 뭐 할려고 하면 최선을 다하는 쪽으로. (문제라면 한다는게 단기간 스퍼트의 경우이다..)

 고지식 (이라 쓰고 애늙은이라 해석) 적인 면이 좀 있음.
 심지어는 얼굴도 노안이어서 여친이나 결혼같은건
 일찍 포기한 채 생활중. (물론 생길지도 모른다는 희망도 있지만..)


 로리만세.



트위터 아이디 : @dsharp_ (update : 15.03.04)



이글루스 접속 일정

'앱게임해봤습니다' 쓰고 싶을때만..


앱해봤

- 도쿄카지노
- 각의 이슈타리아
- 닌쯔쿠 (nintsuku)


2016/10/20 15:58

list

곧 삭제 예정

1 2 3 4 5 6 7 8 9 10 다음