FX/Houdini_Joy of VEX

Joy of Vex - Recap of Week 2

Gamestonk118 2022. 7. 3. 18:09

복습한 내용과 다시봤더니 이해되는 부분:

Day 5: modulo, more arithmetic tricks (quantising), but show that often a chramp is easier (eg stepped chramp);

Day 5 에는 Modulo (%)을 이용한 식을 배워 어떠한 수치들을 division할때 나머지를 구해 attribute에 적용하는 것을 배웠다. 또한 floor()이 내림으로써, ceil()이 올림으로써, rint()가 반올림으로써 그리고 trunc()가 내림으로써 float값들을 integer로 변환시키는 것을 알 수 있었다. 이러한 function들로 통해 만들어진 수치들을 attribute 즉 @P.y 같은 높이값에 적용시키면 point number가 할당된 포인트 끼리 계단모양같은 쉐입을 형성 하는 것을 알 수 있었다. 또 abs()으로 음수값을 양수로 변환시키는등의 절댓값 수치를 반환하는 function도 배울 수 있었다.

- 마지막 세번째 exercise를 할때 약간 햇갈리는 부분이 있었지만 최대한 여러가지 tweak과 해석들을 통해 어떠한 원리로 작동되는지 간단히는 머릿속에 집어넣을 수 있었다.

- 이번 Day는 생각보다 어려운 면이 많지는 않았던 것같다. 학창시절에 배웠던 수학 내용이 많이 나와서 그런지 다 머릿속으로 개념은 확실히 잘 들어왔던것 같다. 

1. 지난 노트를 통해 어떠한 원리로 작동 되는지 설명을 하였지만 다시한번 상기시키려 같은 내용을 가져왔다.

기존에 있던 코드에서 chramp()의 있는 변수를 @N.x + @Time*chf ("SPEED2"); 식으로 바꾸어 @N.x값이 유동적으로 움직이게끔 만들었다. chramp()에 있는 ramp그래프는 포인트 하나하나가 얼만큼 퍼져나가는지 정의한다. 그리고 이 속성이 적용된 chramp()을 지난시간에 배운 @P = @P + @N과 같은 식과 결합하여 입체적인 지오메트리 상에서 표면적으로 각기 포인트들의 vector 즉 x/y/z 방향에 따라 퍼져 나가게끔 설정하였다.

eg) float f = @N.x + @Time*chf ("SPEED2"); // @N.x값에 @Time을 더해서 역동적인 모션을 취하게끔 만듦. chf()을 통해 타임의 스피드를 조정.
f = f/chf ("FACTOR"); // 변수 f의 ramp의 높이값들과 간격들은 chf("FACTOR")로 유동적으로 조절가능케함. 이 간격의 조정에 따라 지오메트리가 얼마나 ramp를 촘촘하게끔 유지시켜 패턴을 반복시키는지 지정함.
@P = @P + @N*chramp ("RAMP", f); // chramp()을 @N 값으로 곱해주고 이 값을 @P로써 지정함으로써 입체적인 지오메트리에서 표면적 즉 노멀의 방향으로 효과가 나타나게끔 세팅함
@P = @P + @N*chf ("HEIGHT"); // 이미 완성된 ramp에 chf()을 곱하여 얼마나 지오메트리가 팽창이 될건지 세팅함. 0에서 1까지의 range가 세팅된 chramp()을 더욱 늘릴 수 있는 식으로써 @P가 0과 1사이를 넘어 더욱 팽창 가능케함.

2. 이때만 해도 몰랐다... 지옥의 시작인걸...

 

Day 6: point wrangle vs prim wrangle vs detail wrangle, user defined attributes

Day 6에는 point, vertex, primitive로 달라지는 geometry spreadsheet의 결과 그리고 각기 다른 run over로 세팅했을 때 나타나는 geometry의 결과를 분석하였다. point는 말그대로 "후디니가 제공해주고 있는 3D 공간상에서 다룰 수 있는 가장 작은 단위의 결과물이다." point로 설정된 spreadsheet에는 각기 포인트 넘버들이 할당된 포인트들의 위치값들을 비롯한 attribute수치들을 표로 나타낸다. 반면 vertex로 설정된 spreadsheet에는 각각의 primitive를 이루는 point들의 순서와 그 포인트들의  point number를 나타낸다.

그리고 primitive로 설정된 spreadsheet에서는 wrangle node의 run over를 primitive로 설정한 상태에서 @P의 값을 다른 attribute 즉 v@K같이 임의로 설정된 attribute에 저장해주어서 spreadsheet에 뜨게 해준다면 수치는 하나의 primitive의 중심에 있는 포인트 위치를 나타낸다. 그리고 primitive wrangle에서 어떠한 attribute값에 수치를 저장한다면 그 값은 포인트가아닌 primitive전체에 적용되어 블럭같은 모양을 생성한다. 

*후디니에서 geometry를 구성할때는 무조건 point -> vertex -> primitive 순서로 진행되어야 한다.* 

- 위에 작성한 이 VEX 코드

eg) v@K = @P;

@K = @K + {1, 0, 0}; // 같은 경우는 유저가 직접 만든 attribute에 @P값들을 저장하고 그 값들에 알맞은 벡터값들을 계산시키므로 geometry spreadsheet상에서 나타내는 것이 가능하다. 하지만 scene view에서 geometry 결과로 나타나지는 않는다. 

: primitive wranlge에서 윗 코드를 적었을때 나는 primitive geometry spreadsheet상에서 @K가 나타나나는 것을 볼 수 있었다. @K는 @P의 정보를 계승했고 그 값들은 spreadsheet에 고스란히 적혀있는데도 불구하고 scene view에서 지오메트리의 변화를 볼 수 없었다. 나는 @P의 정보를 계승한 K값에 vector {1, 0, 0}을 더함으로써 오른쪽으로 지오메트리가 한칸씩 이동할 것이라 생각했는데 그런 변화는 없었다. 하지만 spreadsheet에는 모든 @K[0]값들이 1씩 더해진 값으로써 업데이트된것을 확인 할 수 있었고 그것은 내 의문을 생기게 했다. 나는 이 결과를 "왜냐면 계산된 값들은 오직 유저가 형성시킨 attribute 즉 @K에서만 적용되었으므로" 라고 해석을 하였다. 애초에 @P은 primitive wrangle에서 직접 작성하여 지오메트리에 변화를 주지 못할 뿐더러 좀 더 풀어보자면 @K은 유저가 직접 만든 attribute로써 아무리 @P의 정보를 가져왔다고 해도 오로지 수치들만 가져왔을뿐 built-in attribute로써와 달리 지오메트리의 직접적인 변화에 효과를 주지 못하기 때문이라고 해석하였다.

1. 위 문단에서 해석한 내용처럼 @K는 유저가 직접 생성한 attribute이고 그 attribute가 @P나 @Cd값과 같은 built-in attributes을 저장하여 수치를 옮겨왔다고 해도 이 수치들은 geometry에 직접적인 영향을 끼치지 않는 값들이다. 그 말은 Primitive Wrangle상에서 @P에 직접적인 수치들을 업데이트 시켜주기 위해 즉 쓰기위하는 것은 불가능하다. 이는 "primitive wrangle상에서의 @P는 읽기만 가능하지 쓰는건 불가능 하므로."

이와 같이 @K에만 식이 적용되지 @P의 대한 정보는 spreadsheet에 뜨지 않는 것을 볼 수 있다.

 

Day 7: using the other inputs on wrangles, do things to geometry based on other geometry

Day 7에서는 wrangle에서 윗 wrangle이나 geometry에서로부터 특정 attribute을 불러오는 point()을 배웠다. 이는 point (현재 wrangle에 꽃혀진 윗 노드가 꽂혀진 input의 넘버, 받아오려는 attribute, 해당 포인트 넘버)로 이루어져 있으며 처음으로 wrangle node상에서 0번이 아닌 인풋들을 확인 할 수 있었다. 그리고 minpos()와 nearpoint()를 배워 해당 0번 인풋으로 이루어진 포인트들로부터, 선언된 eg) minpos (1, @P); 인풋 넘버로 꽂혀진 node의 geometry를 이루는 포인트들중 가장 가까운 포인트들의 특정 attribute를 찾는 것이 가능해졌다. 두 function의 가장 큰 차이점은 minpos()는 vector값을 반환하는 상태임에 반면 nearpoint()는 오직 integer값만 반환시킨다는 사실을 알 수 있었다. 이는 강의를 들을땐 모호했지만 이번 숙제를 시도해보면서 확실하게 이해가 됬던것 같다. 

- minpos()에서의 두번째 인풋은 반환 하려는 정보의 attribute으로 알고 있다. 비슷하게 nearpoint()에서 nearpoint()는 배운바로는 minpos()와 다르게 integer value인 @ptnum값만 반환하는 것으로 알고 있는데 굳이 두번째 인풋에 @P를 써야 하는지 의문이 생겼다. 그리고 만약 @ptnum을 반환한다면 @ptnum을 써야하는것이 아닌가라는 의문이 들기도 하였다. 혹시 nearpoint()에서 반환하려는 integer값이 point number뿐만이 아닌 또 다른 값이 있나? nearpoint()에 있는 두번째 인풋의 정확한 뜻을 내가 잘못 알고 있나?라는 아리송한 생각이 들곤 하였다. cgwiki님의 사이트와 twa선생님의 강의에서는 두번째 인풋안에 @P만 쓴 경우를 보여주어 minpos()상에서는 반환하려는 vector attribute가 많다 그렇지만 nearpoint()에는 과연 @ptnum이나 @numpt말고의 다른 integer attribute들이 뭐가 있을지 궁금케했다. 그것도 그렇지만 우선적으로 그렇다면 nearpoint()의 두번째 인풋에 @P를 굳이 써야 하나라는 생각이 들었다. @P는 벡터값인데 왜 nearpoint()에도 두번째 인풋에 @P을 넣을까 라는 궁금증이 들었다.

- 항상 그렇지만 이번 강의와 공부는 복습과 복습을 반복하면서 코드 한줄 한줄 곱씹으면서 작업했던 것같다. 

1. nearpoint()는 @ptnum값을 가져온다기 보단 0번으로 들어온 geometry를 이루는 포인트들중 가장 가까운 포인트들의 넘버를 입력하라라는 식으로 이해하면 됨으로 그 포인트들의 위치값을 확실히 알기 위해 @P를 썼던것 같다. 그로인해 nearpoint()는 integer값인 포인트 넘버를 가져온다는 식으로 이해하면 될것이고 그 다음의 응용같은 경우는 진도를 나가며 배울 것 같다. 솔직히 내가 쓰면서도 아직 모호하고 확실치 않아 나중에 물어봐야 할 것 같다. 

 

Day 8: noise, various types, how it can be scaled, vector vs scalar noise, why you might use vops here instead

Day 8에는 noise()을 vex와 vop에서 각기 다른 방법으로 조절 할 수 있는 방식에 대해 배웠다. noise()는 일반 sin()이나 cos()같은 파형과는 다르게 랜덤한 값으로 파형을 이루는 포인트들의 수치들이 정해지지만 random()과는 명백한 차이를 보인다. random()은 파형을 쪼개면 쪼갤수록 더욱 다채로운 랜덤값을 이루는 반면,  noise()는 커다란 흐름이 잇는 상태에서 random값을 제어를 해줌으로 노이즈가 가진 고유한 흐름을 유지한다. 그리고 random()은 sin()과 비슷하게 안에 들어가는 input을 계산시켜 frequency (파장의 길이), offset (파형을 이루는 포인트들의 수치변경), 그리고 amplitude (파형의 높이)를 조절 가능케 하며 이로 인해 유저가 직접 자신의 마음대로 파형을 커스터마이징 하는 것을 볼 수 있었다. 

- Attribute VOP이 아닌 VEX만을 사용하여 어떻게 noise()로형성된 노이즈 쉐입을 흑백으로 바꿔주는 것이 궁금하였다. 분명 vex에서의 noise()의 기본적인 파형은 3D vector값으로 지장되있는것으로 추론할 수있었다. 그렇다면 이 3D vector값을 1D float값으로 바꾸어 vex상에서 모든 노이즈를 어떻게 @Cd에 저장하였을때 흑백으로 나타날 수 있는지 궁금하였다.

- 내가 시도한 curlnoise()는 앞에 (float)을 선언 하여 3D vector값을 1D float값으로 바꾸어 색상을 흑백으로 바꾸는 것이 가능하였는데 noise()상에서 똑같이 하면 vex상에서 에러가 났다. curlnoise()와 일반 noise()가 다른걸까라는 의문점을 낳게 하였다.

1. 만약 식이 @Cd = chf("GRAYSCALE")*noise (input); 이렇게 써있을때 위와 같은 식으로 chf()을 곱해주어 흑백으로 3D값을 1D값으로 전환시켜 색상을 흑백으로 전환시키는 것이 가능하였다. 이는 곱셈을 한 수치들을 따로 따로 @Cd로 저장 시켰을때는 동일 한 결과가 나오지 않아 새로운 궁금증을 야기시켰고 스팅고님의 추측으로 이는 아마 스케일 디멘션에 따라서 노이즈의 디멘션이 결정되는 것이라 추론을 내릴 수 있었다. 더욱 자세한건 TWA선생님께서 설명해 주신다고 예고하셨다.

2. 이는 아직도 이해가 가지 않는다. 단순한 오류인지 정확한 이유가 있는지는 아무리 구글링을 해봐도 나오지 않았다. 앞에 (float)을 넣는 것이 잘못되었는지 아니면 둘 중의 차이가 있는건지 아니면 다른 이유가 있는건지 궁금해지기 시작하였다.

이처럼 curlnoise()앞에 (float)을 붙여 기존의 3D vector값을 1D float 값으로 바꿔주려는 시도는 성공적이었다. 하지만 일반 noise()에서는 작동되지 않았다.

 

다시봐도 모르겠는 부분:

- 앞서 언급한 Day 7에서의 nearpoint()에 들어가는 두번째 인풋의 정체에 대해 그리고 nearpoint()가 반환하는 integer값중 오직 point number만 해당되는지 아직도 감이 쉽사리 잡히지 않는 것 같다. 아니면 내가 들어가지는 두번째 인풋 정보에 대해 확실하게 이해 못한건지 모를지도 모르겠다. 

- Day 8의 첫번째 막혔던 부분 정확히 noise() 3D 값을 1D로 전환시키기 위해 chf()을 곱해주는 시도를 했더니 작동되었다. 그리고 따로 적용하면 되지 않았다. 아마 이 부분은 noise()에 직접적으로 계산을 시켜줘야 성공적으로 dimension을 전환시킬 수 있다고 추측하였다. 그리고 곱해주는 상수의 dimension에 따라 결과 dimension이 정해진다는 추측을 하였다. 정확한 설명은 TWA선생님의 해설을 들어야 할 것같다.

- 이 부분은 넘어가도 될 부분인듯 하면서도 단순한 오륜지 아닌지는 궁금증을 자아나게 한다. curlnoise()가 뭔지 정확히 공부해서 알아야할 필요 즉 더욱 다양한 noise들을 탐색해봐야 할 필요를 느꼈다. 그리고 이렇게 나타나는, vex로써 noise()를 다루는 위험성을 미리 느껴 vop의 고마움을 느끼게 되었다.