FX/Houdini_Joy of VEX

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

Gamestonk118 2022. 6. 27. 17:13

중요했던 부분:

- %: Modulo

모듈로, 즉 어떤 수를 어떤 수로 나누었을때 나머지가 생기는데 그 결과값을 도출해내는 것이 모듈로임.

eg) 8%6 = 2

eg) int num = chi ("NUM"); // 나누어지는 숫자

int div = chi ("DIV"); // 나누는 숫자

int result = num%div; // num에서 div로 나누었을 때 생기는 나머지값을 int variable result에 저장하라

// 모든 변수의 값들을 geometry spreadsheet에서 보기 위해 attribute로 변환시켜라

i@num = num;

i@div = div;

i@result = result;

만약 num과 div가 모두 float이고 result를 float으로 선언하였을때

eg) float num = 5; // num은 5

float div = 1.5; // div는 1.5

float result = num%div; // result는 결국 결과값으로 0.5를 나타냄. 5에서 1.5를 나누면 몫은 3 그리고 나머지는 0.5가 되므로. 그러므로 모듈로는 float으로 type casting을 했을 당시에도 모듈로 값을 나타낼 수 있음을 알 수 있음.

 

- 모듈로를 이용한 지오메트리 형성

모듈로를 이용하게되면 특정 구간을 기준으로 반복되는 형태의 지오메트리 결과를 얻어낼 수 있음

eg) // add 노드들을 이용하여 선을 만들었다고 가정시에

float div = chf ("DIV"); // chf()로써 유저가 파라미터를 조정할 수 있는 변수 div를 선언

float height = @P.x/div; // @P.x값에서 변수 div를 나눈 값을 변수 height에다 저장

// @P.x를 더욱 큰값으로 곱하면 경사면이 가파라지고 나누면 원만해지기 때문에 이 식에서는 div값을 높일수록 경사면이 완만해져가는 라인을 볼 수 있다.

@P.y = height; // 변수 height값을 @P.y값에다 저장 (지오메트리의 높이로써 변화를 줌)

기본적인 @P.y = @P.x 라는 식의 속성을 공유하는 결과로써 윗 코드의 결과를 나타낸다.

하지만 float height = @P.x/div; 이 식을 모듈로로써 적용하였을때...

eg) // 모듈로로 계산된 값들은 나누려는 숫자가 커져도 나누는 숫자가 같으면 특정 숫자들이 반복되는 특징을 지님.

0.2/1 = 0...0.2

0.4/1 = 0...0.4

0.8/1 = 0...0.8

1/1 = 1...0

1.2/1 = 1...0.2

1.4/1 = 1...0.4

1.8/1 = 1...0.8

// 음수가 되어도 나머지 값들은 양수로 유지됨. 그러므로 지오메트리는 양수 음수 상관없이 계속 반복되는 패턴을 지니게됨.

-1.6/1 = -1...0.4

-1.2/1 = -1...0.2

이러한 특징을 삼아 float height = @P.x/div;를 float height = @P.x%div;로 변환하였을때

윗 코드에서 식을 기본적인 division에서 modulo로 변환하였을때 나머지 값들을 @P.y높이값으로 도출해내므로 위 사진과는 다른 반복되는 특징의 패턴을 나타내는 특징을 구현한다는 것을 알 수 있다.

이와 같은 결과를 나타냄.

 

eg) @P.y = @ptnum%5; // 0%5 = 0, 1%5 = 1...5%5 = 0, 6%5 = 1, 7%5 = 2와 같이 1부터 5의 숫자들이 반복되는 결과를 @P.y에다 저장시킴. 대신 5를 ch()으로 이용하여 더욱 유동적으로 파라미터로써 조절하게끔 가능케 할수 있음

eg) float color = @Time%1; // @Time은 기본적으로 24프레임을 기준으로 이 Attribute값을 1로 모듈로 해준다면 24마다 반복되는 겨로가를 얻을 수 있음. 그 반복되는 결과값들을 float variable color에 저장시킴

f@color = color; // 방금전 선언된 color 변수를 attribute color로 저장시켜 geometry spreadsheet에 디스플레이함

@Cd = 0; // 모든 @Cd 값들 0으로 초기화

@Cd.r = color; // color변수를 @Cd.r에 지정하여 지오메트리에 빨간색을 입힘. 위에 선언된 @Time에 모듈로가 계산된 color변수로 인에 빨간색이 24프레임마다 색상이 선명해졌다 다시 0으로 검정색으로 전환되고 이 패턴이 반복되는 결과를 적용할 수 있음.

만약 내가 float color = @Time%ch ("TIMING"); // 과 같이 @Time에 모듈로한 상수값을 ch()으로 바꿔줌으로써 반복되는 속도를 조정할 수 있음. ch()에 적용된 Timing값은 반복되는 수치의 최대의 값으로 작동됨. (eg. 만약 12가 TIMING 파라미터에 입력되었으면 최대 @Cd.r값은 12까지 올라갈 수 있음. 그 이상 올라가려는 값들은 다시 0으로 전환됨).

 

- abs(): Absolute Value Function (절댓값 함수)

abs()는 모든 수를 절댓값으로 변환 시키는 function이다.

eg) @P.y = abs (@P.x); // 모든 음수값들이 양수로 변환되어 높이값으로 assign해준다면 깔대기 형태의 모양이 나오게 됨

절댓값 function인 abs()을 @P.x값에 적용하여 높이값으로 나타냈을때의 지오메트리

- floor(): Floor Function (내림)

모든 float값들이 정수(integer)로 변환됨과 동시의 소수점이 있는 숫자들을 전부 내림시킴.

eg) 0.1 -> 0, 2.8 -> 2, -0.3 -> -1, -2.8 -> -3

eg) @P.y = floor (@P.x); // @P.x값에 floor function을 적용하여 모든 float포인트들에게 내림이 적용된 모양의 지오메트리를 형성함

floor()으로 인해 내림이 적용되어 예를 들면 0에서 1까지의 점들은 모두 0으로 내려온 사실을 알 수 있다. 또한 음수의 값 즉 -1에서 0까지의 값들은 전부 -1로 내려온 사실을 알 수있다.

- ceil(): Ceil Function (올림)

모든 float값들이 정수(integer)로 변환됨과 동시의 소수점이 있는 숫자들을 전부 올림시킴.

eg) 0.1 -> 1, 2.8 -> 3, -0.3 -> 0, -2.8 -> -2

eg) @P.y = ceil (@P.x); // @P.x값에 ceil function을 적용하여 모든 float포인트들에게 올림 적용된 모양의 지오메트리를 형성함

ceil()으로 인해 올림이 적용되어 예를 들면 0에서 1까지의 점들은 모두 1로 올라온 사실을 알 수 있다. 또한 음수의 값 즉 -1에서 0까지의 값들은 전부 0으로 올라온 사실을 알 수있다.

- rint(): Rint Function (반올림)

모든 float값들이 정수(integer)로 변환됨과 0.5를 기준으로 하여 이 0.5보다 높은 값들은 올림시키고 0.5를 포함해서 더 낮은 값들은 내림시킴.

eg) 0.1 -> 0, 2.8 -> 3, -0.3 -> 0, -2.8 -> -3

eg) @P.y = rint (@P.x); // @P.x값에 rint function을 적용하여 모든 float포인트들에게 반올림이 적용된 모양의 지오메트리를 형성함

rint()으로 인해 반올림이 적용되어 예를 들면 0에서 0.5까지의 점들은 모두 0으로 내려온 사실을 알 수 있다. 반면 0.6에서 1까지의 점들은 모두 1로 올라온 사실을 알 수 있다.또한 음수의 값 즉 -1에서 -0.6까지의 값들은 전부 -1로 내려온 사실을 알 수있고 -0.5에서 0까지의 값들은 전부 0으로 올라온 사실을 알 수 있다.

- trunc(): Trunc Function (버림)

모든 float값들이 정수(integer)로 변환됨과 오직 순수하게 소수점 자리의 수들만 없애는 함수. floor()와 차이에 있어서 음수의 값을 변환시키는데 잇어 다름.

eg) 0.1 -> 0, 2.8 -> 2, -0.3 -> 0, -2.8 -> -2 // floor()은 음수의 값을 내림시키는 반면 trunc()는 순수하게 소수점의 있는 수를 없애는 형식으로 작동되다보니 양수의 값들은 내림의 형태가 되고 음수값들은 올림의 형태를 가지게됨)

eg) @P.y = trunc (@P.x); // @P.x값에 trunc function을 적용하여 모든 float포인트들에게 있어 양수는 내림이 적용되고 음수는 올림이 적용되는 모양을 높이값으로 가지게됨.

trunc()으로 인해 버림이 적용되어 예를 들면 0에서 1까지의 점들은 모두 1로 내려온 사실을 알 수 있다. 또한 음수의 값 즉 -1에서 0까지의 값들은 전부 0으로 올라온 사실을 알 수있다. 이러한 특징을 통해 trunc()는 일반적인 어림 function들과 다르게 점대칭으로써 나타나지는 사실을 알 수 있다.

 

- Advanced Calculations

eg)

float d = length (@P); // 모든 포인트와 원점사이의 거리 길이

float f = chf ("FACTOR"); // ch()로 지정한 값을 변수 f에 저장

d = d/f; // 앞서 선언된 변수 d를 또다른 변수 f로 나눔. 이말은 나중에 @P.y에 d를 저장했을때 경사값을 조절 할 수 있게 함. 곱셈이 아닌 나눗셈의 결과로써 f의 값이 올라 갈 수 록 더욱 경사가 완만해짐.

d = trunc (d); // trunc()로 소수점을 없앰 (계단식 모양을 형성)

float height = d; // d를 새로운 변수 height에 저장

@P.y = height; // height을 지오메트리의 높이값 즉 @P.y의 형태로 보여줌. d가 length()로 절댓값과 비슷하게 거리로 측정되었으므로 음수의 거리길이는 불가능하므로 대칭적인 모양을 보여줌.

윗 코드를 이용하여 만들어낸 지오메트리. trunc()으로 인해 기존에 깔대기 모양이었던 지오메트리가 계단식으로 형성된 것을 알 수 있다.

 

- Faking trunc with a chramp()

chramp()을 사용하여 trunc와 비슷한 결과를 지오메트리에서 구성할 수 있다는 사실을 증명하기 위해 직접 실험해 보았다.

eg)

float d = length (@P); // 모든 포인트들부터 원점까지의 거리

d = d/chf ("FACTOR"); // d를 나눔으로써 경사를 조정 가능케함. 여기 있는 ch()을 조정하여 반복되는 grid에서 반복되는 패턴의 횟수 그리고 간격들을 조절할 수 있다.

float height = d; // d를 새로운 변수 height에 저장. 

@P.y = chramp ("RAMP", height); // chramp()을 활용하여 계단식 모양을 만듦. 하지만 chramp()은 높이값을 0에서 1까지의 구간으로 제한시킴으로 방금전 사용한 윗 코드와는 다르게 패턴이 끝나면 다시 0에서 부터 올라가는 반복되는 형태를 구성함.

@P.y = @P.y*chf ("HEIGHT"); // 이미 만들어진 계단 값에 @P.y에 chf()에 지정된 값을 곱해 높이를 조정

chramp()을 활용한 계단식 지오메트리. 파라미터 factor을 조정하여 반복되는 형태의 계단들을 지오메트리 상에서 보이지 않게끔 조정하여 최대한 trunc()을 활용한 윗 코드와 비슷하게 보이게끔 설계하였다.

Exercises:

1. try the different interpolation modes on the points of the ramp

Interpolation을 기존에 세팅되었던 constant에서 catmull-rom으로 바꾸고 ramp모양도 약간의 수정을 하여 곡선적인 형태의 계단모양을 구축하였다.

ramp의 모든 포인트들의 Interpolation을 catmull-rom으로 바꾸어 곡선적인 형태로 바꾼 지오메트리의 모습

2. using interpolation, see how few points you can use to define a sine wave

ramp을 이것저것 파라미터들과 함께 수정한 결과 정상적인 sine을 만들려면 8개의 포인트들이 충분한 것으로 결과를 내렸다.

기존에 있던 코드방식에서 chramp()의 있는 ramp그래프들을 활용하여 최소 포인트들의 갯수들만을 이용해 만든 sine wave를 나타내는 grid

3. think of other inputs you can use to drive the ramp. Components of P? Components of Cd or N? Current Time or current @Frame? If those things aren't in a 0:1 range like chramp expects, how do you fit them to the range you need?

chramp()안에 들어가는 인풋들의 attribute를 여러가지 넣어보아 화려한 결과를 얻기위해 @N.x에서 @Time이 더해진 값을 한번 넣어보아 시험해보았다.

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사이를 넘어 더욱 팽창 가능케함.

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

 

이해가 안되었던 부분:

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

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

 

공부하면서 들었던 생각:

분명 배운건 모듈로, 어림등의 계산식과 function들인데 exercise는 모두 전시간에 배웠던 chramp()에 관한거라 cgwiki님의 의도가 매우 궁금해졌다. 그만큼 chramp()의 중요도가 Joy of Vex시간에 있어서 무척 중요하다는 것으로 이해가 된것같다. 생각보다 지난 수업보다는 쉬워서 조금 수월하게 이번 day는 넘길 수 있었던 것같다. 모듈로와 어림값으로 변환하는 function들이 지오메트리의 모양에 영향을 줄때 너무 신기하고 재밌었던것 같고 수학의 아름다움을 느낄 수 있었던것 같다. 후디니를 배우면서 내가 CG를 배우는건지 기하학을 배우는건지 햇갈리는 것같지만 다 피가되고 살이 될것이라는 것을 알 수 있다. 다음 6일차에서 7일차부터는 완전 헬이라는데 내가 지난번에 독학으로 7일차까지 배웠던지라 기억을 상기시키면 생각보다 빠르게 이해할 수 있을것 같다. 어서 빨리 vex를 익히고 내가 만들고 싶은 것을 후디니로 구현시키고 싶은 욕망이 공부하면 공부할 수록 생겨나는 것같다. 후디니의 애착이 더욱 커져가는 것을 보니 내가 기분이 다 좋은것 같다.