중요했던 부분:
- 0 부터 1까지로 각각의 포인트의 대한 range를 설정해주는 기본적인 방법
만약 line즉 선이 있는데 포인트가 많을때 @P.x값은 기본적으로 원점 (0, 0, 0)을 기준으로 모든 포인트들의 위치를 할당한다. 이렇게 되면 나중에 chramp()와 같은 0에서 1까지의 범위만을 사용하여 파형을 직접 구성해준다든가 할때 어려움을 느낀다. 이럴때 손쉽게 vex를 사용하여 새로운 attribute를 만들어 모든 포인트에 대하여 0에서부터 1까지의 수치들을 각기 다 할당해 줄 수 있다.
// 모든 포인트에 대하여 0에서 1까지의 수치들을 float Attribute rel로써 나타내어라
f@rel = float (@ptnum)/(@numpt - 1);
// @numpt에 float값이 된 @ptnum을 나누어 시작점에서부터 끝점까지 모든포인트에게 0부터 1까지의 값을 할당함.
// @numpt에 -1을 하여 1까지 딱 떨어지도록 만든다. 이는 수직선의 규칙에 따라 나누는 값이 -1되어야 알맞게 나누어지므로.
이는 후에 배운 relpointbbox()로 좀 더 쉽게 vector값인 geometry를 0에서 1까지의 수치로 바꿔줄 수 있다.
- 코드의 변화/코드 예쁘게 쓰기
지금까지 배워왔던 코드를 쓰는 방식은 하나하나 이펙트 (Effect)를 구별하는데 있어 어려움을 겪었다. 그러므로인해 코드의 쓰는 방식을 바꾸어 조금 더 직관적으로 각각의 코드 라인들이 무엇을 의미하는 지 알수 있게끔하였다.
이는 코드를 생성할때 아래와 같은 차례대로의 방식대로 작성하면 보다 더욱 직관적으로 어떤 효과들이 scene view에서 구현되는지 확인 할 수 있다. 각기 fx가 순차적으로 업데이트될때 해당 업데이트를 지워주거나 하나만 남기게끔 하면 각기 effect 효과들이 어떻게 Geometry를 변화시키는지 알 수 있다.
1. 변수 생성 (float variable fx도 선언)
2. 효과 생성 (effect의 특징을 만들어 어디에 어떻게 저장할 지 지정)
3. 효과를 택 (변수 fx에 effects를 추가)
4. 원본에 저장 (결과로 보는 것)
나는 개인적으로 변수 생성과 효과를 지정해주는 방식을 동시에 진행하는게 편하게 느껴져서 vex를 작성할때 아래와 같은 식으로 썼다. 하지만 이 방법이 맞을지는 후에 가봐야 깨달을 것 같다.
// 모든 포인트에 대하여 0에서 1까지의 수치들을 float Attribute rel로써 나타내어라
f@rel = float (@ptnum)/(@numpt - 1);
// @numpt에 float값이 된 @ptnum을 나누어 시작점에서부터 끝점까지 모든포인트에게 0부터 1까지의 값을 할당함.
// @numpt에 -1을 하여 1까지 딱 떨어지도록 만든다. 이는 수직선의 규칙에 따라 나누는 값이 -1되어야 알맞게 나누어지므로.
// 아랫 노드
/* * 변수 생성 & 효과 생성 * */
// 여기 float variable fx는 전체적인 effect를 추가한 값임. 모든 효과에 대해 정의를 내려준다.
float fx = 0;
// 여기 float variables은 fx에 추가될 수치들로써 각기 어떠한 효과를 나타낼지 정의를 내려준다.
float fxA = sin (@P.x)*chf ("A"); // 모든 포인트의 x값에 대해 sin()의 결과물
/* 여기서부턴 noise()을 사용하여 들쑥날쑥한 파형을 구현시키도록 하였다. 그리고 noise()안에 들어가는 인풋에
각기 알맞는 상수들을 곱해주어 Frequency를 조절해주기로 하였다. 그리고 중요한 것으로 noise()는 기본적으로
높이값이 0과 1의 range값으로 설정되있기 때문에 scene view상에서 정가운데 위치하지 못하게 된다. (그러므로 noise()
가 쌓이면 쌓일수록 geometry의 높이가 올라가게 된다)
이러한 이유로 fit()을 적용하여 -0.5와 0.5의 range값으로 조정하여 정가운데 위치하게끔 설정하였다.
또한 모든 effect뒤에 chf()값을 곱해줌으로써 유저들이 직접 파라미터로 effect의 scale즉 noise()상에서 파형의
높이값을 조절할 수 있게 하였다*/
float fxB = fit (noise (@P.x), 0, 1, -0.5, 0.5)*chf ("B");
float fxC = fit (noise (@P.x*10), 0, 1, -0.5, 0.5)*chf ("C");
float fxD = fit (noise (@P.x*50), 0, 1, -0.5, 0.5)*chf ("D");
/* 위에서 선언한 (0에서 1까지의 범위)를 지정해준 f@rel을 이용하여 chramp()을 적용하여 범위안의 수치값들을
유저가 직접 ramp로 조절 할수 있게 하였다*/
float whereA = chramp ("WHEREA", @rel);
float whereB = chramp ("WHEREB", @rel);
float whereC = chramp ("WHEREC", @rel);
float whereD = chramp ("WHERED", @rel);
/* * 효과를 택 * */
/* 맨 위에 선언한 float variable fx에 모든 effect 변수와 ramp변수들을 차례대로 추가하여 fx를 순차적으로
업데이트 해주었다. 이때 더하기를 라인마다 쓰는것이 직관적이고 좋다*/
// ramp에서 지정한 0에서 1까지의 범위 안에서의 수치값에 따라 할당된 effect가 반영된다
fx += fxA*whereA;
fx += fxB*whereB;
fx += fxC*whereC;
fx += fxD*whereD;
/* * 원본에 저장 * */
/* 방금 전 추가해준 모든 ramp안에 지정된 수치값에 따라 반영된 effect들을 포함하는 float variable fx를
@P.y 높이값으로 보여주어라*/
@P.y += fx;
/* * 변수 생성 & 효과 생성 * */
// 여기 float variable fx는 전체적인 effect를 추가한 값임. 모든 효과에 대해 정의를 내려준다.
vector fx = 0;
// 나중에 선언될 vector variable fxA에 오리지널 effect값을 만들어 주어 이 녀석에서 효과가 나타나도록 설정
vector oA = noise (@P);
/* 중요한 것으로 noise()는 기본적으로
높이값이 0과 1의 range값으로 설정되있기 때문에 scene view상에서 정가운데 위치하지 못하게 된다. (그러므로 noise()
가 쌓이면 쌓일수록 geometry의 높이가 올라가게 된다)
이러한 이유로 fit()을 적용하여 -0.5와 0.5의 range값으로 조정하여 정가운데 위치하게끔 설정하였다. */
// 아까와는 다르게 x/y/z값을 이용하여 따로따로 설정해주어 입체적인 geometry에서도 작동되게끔 함
float oAx = fit (oA.x, 0, 1, -0.5, 0.5);
float oAy = fit (oA.y, 0, 1, -0.5, 0.5);
float oAz = fit (oA.z, 0, 1, -0.5, 0.5);
// 나중에 선언될 vector variable fxB에 오리지널 effect값을 만들어 주어 이 녀석에서 효과가 나타나도록 설정
// noise()안에 들어가는 인풋에 상수를 곱해줌으로써 Frequency값을 조정
vector oB = noise (@P*7);
// 아까 oA의 대한 vector값에 적용하던 fit()을 반복해 알맞은 range를 설정해 준다.
float oBx = fit (oB.x, 0, 1, -0.5, 0.5);
float oBy = fit (oB.y, 0, 1, -0.5, 0.5);
float oBz = fit (oB.z, 0, 1, -0.5, 0.5);
// 앞서 설정된 모든 effect값들을 vector variables을 각기 fxA와 fxB에 저장함
// 그리고 그 값들에 또 상수를 곱해줌으로써 각기 effect의 scale값을 조정. 여기선 noise()의 파형 높이값이 될거임
vector fxA = set (oAx, oAy, oAz)*1.3;
vector fxB = set (oBx, oBy, oBz)*0.1;
/* * 효과를 택 * */
/* 맨 위에 선언한 float variable fx에 모든 effect 변수와 ramp변수들을 차례대로 추가하여 fx를 순차적으로
업데이트 해주었다. 이때 더하기를 라인마다 쓰는것이 직관적이고 좋다*/
fx += fxA;
fx += fxB;
/* * 원본에 저장 * */
/* 방금 전 추가해준 모든 ramp안에 지정된 수치값에 따라 반영된 effect들을 포함하는 float variable fx를
@P.y 높이값으로 보여주어라*/
@P = @P + fx;
- relpointbbox(): Relpointbbox Function
relpointbbox()에서 rel (relative)는 "상대적인"이란 의미를 가지고, bbox (bounding box)는 "Bounding Box"를 의미한다.
여기서 상대적일때 의미는 위와 같은 식처럼 어느 길이를 가진 range값이든 0에서 1까지로 범위를 지정해주어 그 사이값들이 알맞게 지정되는 것을 뜻한다.
Bounding Box는 geometry가 있을때 그 geometry를 안에 집어넣는 box로 사이즈는 geometry의 최대 X/Y/Z값을 기반으로 하여 만들어진다. 이때 안에 있던 Geometry가 rotation이 된 상태여도 bounding box는 같이 rotation되는 것이 아닌 rotation상태의 geometry의 최대 x/y/z값을 계산하여 새로운 bounding box를 생성한다.
- bound
연결된 Geometry의 bounding box를 생성할 수 있게 해주는 노드
즉 relpointbbox()는 우리가 가진 가장 큰 값 그리고 가장 작은값을 기준으로 0부터 1까지의 숫자로 표현해주는 function이다. 이때 한방향인 아닌 vector값으로써 x/y/z값을 모두 구해주어 입체적인 Geometry를 상대로 적용 가능하다. 위에 설명한 @ptnum/@numpt의 입체적인 형태로 이해하면 편하다.
이는 특히 chramp()같은 function을 쓸때 유용한데 기본적으로 chramp()는 range값을 0에서 1까지로 지정하였다. 그러므로 geometry상에서 사이즈가 1을 넘어가면 chramp()에서 지정된 ramp가 Geometry상에서 반복되기 일쑤였다. 하지만 relpointbbox()로 geometry의 모든 포인트들의 수치를 0-1사이의 수치로 맞춘 variable이나 attribute를 chramp()인풋에 집어넣어주면 ramp가 반복되지 않고 전체적으로 geometry에 적용되는 것을 알 수 있다.
/* 첫번째 인풋은 wrangle node에 geometry가 연결된 input넘버
그리고 두번째 인풋은 어떤 vector attribute값을 되돌려 줄지 지정한다. */
v@rel = relpointbbox (0, @P);
방금 전 배운 relpointbbox()를 사용하여 마음대로 grid의 형상을 조절할 수 있다.
// relpointbbox()를 사용하여 모든 포인트의 vector variable rel값이 전부 0에서 1까지의 수치로 지정되게함
vector rel = relpointbbox (0, @P);
// 선언된 vector variable rel값을 float x/y/z으로 나누어 나중에 코드를 작성할때 각기 따로 적용할 수 있게함
// 첫번째 effect (fxA)의 ramp를 위한 float variables
float rXa = rel.x;
float rYa = rel.y;
float rZa = rel.z;
// 두번째 effect (fxB)의 ramp를 위한 float variables
float rXb = rel.x;
float rYb = rel.y;
float rZb = rel.z;
// 이는 나중에 chramp()을 이용하여 0부터 1까지의 range로 지정된 geometry의 Ramp생김새를 지정할 수 있게함
// 나중에 effect를 추가할때 ramp에 지정된 수치만큼 effect가 구현됨
rXa = chramp ("rx", rXa);
rZa= chramp ("rz", rZa);
rXb = chramp ("rxb", rXb);
rZb= chramp ("rzb", rZb);
/* * 변수 생성 & 효과 생성 * */
// 여기 float variable fx는 전체적인 effect를 추가한 값임. 모든 효과에 대해 정의를 내려준다.
vector fx = 0;
// 나중에 선언될 vector variable fxA에 오리지널 effect값을 만들어 주어 이 녀석에서 효과가 나타나도록 설정
vector oA = noise (@P);
/* 중요한 것으로 noise()는 기본적으로
높이값이 0과 1의 range값으로 설정되있기 때문에 scene view상에서 정가운데 위치하지 못하게 된다. (그러므로 noise()
가 쌓이면 쌓일수록 geometry의 높이가 올라가게 된다)
이러한 이유로 fit()을 적용하여 -0.5와 0.5의 range값으로 조정하여 정가운데 위치하게끔 설정하였다. */
// 아까와는 다르게 y값만 이용하여 설정해주어 높이값으로만 작동되게끔 함
float oAy = fit (oA.y, 0, 1, -0.5, 0.5);
// 나중에 선언될 vector variable fxA에 오리지널 effect값을 만들어 주어 이 녀석에서 효과가 나타나도록 설정
// noise()안에 들어가는 인풋에 상수를 곱해줌으로써 Frequency값을 조정
vector oB = noise (@P*4);
// 아까 oA의 대한 y값에 적용하던 fit()을 반복해 알맞은 range를 설정해 준다.
float oBy = fit (oB.y, 0, 1, -0.5, 0.5);
// 앞서 설정된 모든 effect값들을 vector variables을 각기 fxA와 fxB에 저장함
// 그리고 그 값들에 또 상수를 곱해줌으로써 각기 effect의 scale값을 조정. 여기선 noise()의 파형 높이값이 될거임
/* 또한 앞서 chramp로 만들어준 ramp를 또 적용하여 ramp안에 지정된 0부터 1까지의 알맞은 수치들에 따라 effect가
반영되게함.*/
// 여기선 두 effect모두 x와 z값을 할당하는 Ramp값만 적용함
vector fxA = set (0, oAy,0)*50*rXa*rZa;
vector fxB = set (0, oBy, 0)*1.2*rXb*rZb;
/* * 효과를 택 * */
/* 맨 위에 선언한 float variable fx에 모든 effect 변수와 ramp변수들을 차례대로 추가하여 fx를 순차적으로
업데이트 해주었다. 이때 더하기를 라인마다 쓰는것이 직관적이고 좋다*/
fx += fxA;
fx += fxB;
/* * 원본에 저장 * */
/* 방금 전 추가해준 모든 ramp안에 지정된 수치값에 따라 반영된 effect들을 포함하는 float variable fx를
@P.y 높이값으로 보여주어라*/
@P = @P + fx;
// relpointbbox()를 사용하여 모든 포인트의 vector variable rel값이 전부 0에서 1까지의 수치로 지정되게함
vector rel = relpointbbox (0, @P);
// 선언된 vector variable rel값을 float x/y/z으로 나누어 나중에 코드를 작성할때 각기 따로 적용할 수 있게함
// 여기서는 y값만 지정해주어 y방향을 축으로 ramp에따라 늘어나게끔 설정함
float rY = rel.y;
// 이는 나중에 chramp()을 이용하여 0부터 1까지의 range로 지정된 geometry의 Ramp생김새를 지정할 수 있게함
// 나중에 effect를 추가할때 ramp에 지정된 수치만큼 effect가 구현됨
rY = chramp ("rY", rY);
// 여기 float variable fx는 전체적인 effect를 추가한 값임. 모든 효과에 대해 정의를 내려준다.
vector fx = 0;
/* * 효과를 택 * */
/* 맨 위에 선언한 float variable fx에 모든 effect 변수와 ramp변수들을 차례대로 추가하여 fx를 순차적으로
업데이트 해주었다. 이때 더하기를 라인마다 쓰는것이 직관적이고 좋다*/
/* 여기선 @N값에 scale을 더해주어 geometry를 부풀리기로 하는데 ramp값이 곱해져 부풀리는
범위를 유저가 파라미터로 지정가능케함*/
// fx는 더해줄때만 순차적으로 적어주는것이좋다.
fx += @N*chf ("SCALE")*rY;
/* * 원본에 저장 * */
/* 방금 전 추가해준 모든 ramp안에 지정된 수치값에 따라 반영된 effect들을 포함하는 float variable fx를
@P.y 높이값으로 보여주어라*/
@P = @P + fx;
- Attribute Wrangle -> Setting -> Delete All Spare Parameters
ch()으로 만들어졌던 attribute wrangle노드 안의 파라미터들을 모두 전부 삭제해준다.
Exercises:
1. A taper effect from top to bottom
taper effect가 정확히 어떤것을 의미하는지 몰라 구글링을 해봤는데 경제 관련 글밖에 없었다. 계속 찾아보니 대충 위는 크고 아래쪽으로 갈수록 작아지는 그런 쉐입같다고 추측하였다. 그래서 Tommy의 형상을 지정하는 방금 전 위의 코드로 만들어진 chramp()안의 ramp파라미터를 조정하여 구현해 보았다.
2. Noise that scales left to right across a grid
아까 grid에 ramp안에 있는 수치에 따른 effect의 반영을 적용한 코드에서 float variable rZa와 rZb를 제거하고 (아래 이미지에 밑에서 두개의 ramp파라미터들) 오직 rXa와 rXb만을 effect수치에 곱하여 일정한 한 방향 (x 방향)으로 ramp의 형상이 진행되게끔 하였다.
그리고 ramp파라미터들을 기본값으로 바꿔 문제에 나와있듯이 왼쪽에서 오른쪽으로 갈수록 점차적으로 noise 파형이 세지는 그런 형상을 만들고 또한 effect에 상수값을 더하여 파형의 최대 높이값을 조절할 수 있도록 하였다. grid의 사이즈도 확장시켜봤는데 relpointbbox()가 적용되어 그런지 ramp가 반복되지 않는 것을 확인 할 수 있었다.
// 윗 코드에서 이 부분을 수정하여 새로운 모양의 grid를 형성
vector fxA = set (0, oAy,0)*20*rXa;
vector fxB = set (0, oBy, 0)*1.2*rXb;
3. Colour driven by a ramp, so you get this kind of control:
아까 Tommy에 적용했던 코드에서 fx에 할당된 값을 rel.y값으로 바로 설정해주어 y축을 중심으로 tommy의 둘레에 따라 effect가 형성되도록 세팅하였다. 또한 chf()을 곱해주어 effect의 스케일 값도 조절할 수 있게끔 설정하였다.
그리고 그 effect가 @Cd (색깔 값)으로 지정될 수 있게끔 fx를 @Cd값에 적용하였다.
// relpointbbox()를 사용하여 모든 포인트의 vector variable rel값이 전부 0에서 1까지의 수치로 지정되게함
vector rel = relpointbbox (0, @P);
// 선언된 vector variable rel값을 float x/y/z으로 나누어 나중에 코드를 작성할때 각기 따로 적용할 수 있게함
// 여기서는 y값만 지정해주어 y방향을 축으로 ramp에따라 늘어나게끔 설정함
float rY = rel.y;
// 이는 나중에 chramp()을 이용하여 0부터 1까지의 range로 지정된 geometry의 Ramp생김새를 지정할 수 있게함
// 나중에 effect를 추가할때 ramp에 지정된 수치만큼 effect가 구현됨
rY = chramp ("rY", rY);
// 여기 float variable fx는 전체적인 effect를 추가한 값임. 모든 효과에 대해 정의를 내려준다.
vector fx = 0;
/* * 효과를 택 * */
/* 맨 위에 선언한 float variable fx에 모든 effect 변수와 ramp변수들을 차례대로 추가하여 fx를 순차적으로
업데이트 해주었다. 이때 더하기를 라인마다 쓰는것이 직관적이고 좋다*/
/* rY값 즉 y축을 중심으로 ramp가 형성되는 effect를 fx변수에 추가시켜주었다. 그리고 chf()을 설정하여
Ramp의 스케일을 파라미터로 조절 가능케 하였다*/
fx += rY*chf ("SCALE");
// 아니면 또한 이렇게 @Cd값에 ramp수치를 더한 값을 fx변수에 추가시켜주는 방식도 가능하다
fx += @Cd*rY*chf ("SCALE");
/* * 원본에 저장 * */
@Cd = 0; // @Cd 색깔값을 0으로 초기화
/* 방금 전 추가해준 모든 ramp안에 지정된 수치값에 따라 반영된 effect들을 포함하는 float variable fx를
@Cd 색깔값으로 보여주어라*/
@Cd = @Cd + fx;
이해가 안되었던 부분:
- 의외로 길었던 강의와는 대조되게 엄청나게 어려웠던 부분은 이번강의에서는 없었던 것 같다. 오히려 지난번 chramp()을 배웠을때 찜찜했던 궁금증을 해소시켜주었던 것 같다. relpointbbox()의 첫 인상은 매우 어려울 것 같았지만 bounding box를 통해 시각적으로 보니 이해가 바로 되었던 것 같다. 그리고 또한 코드를 예쁘게 쓰는 방법을 알고 나니 effect마다 햇갈리지 않고 구분지어 특정 Geometry를 구현할 수 있겠다는 생각이 들었다.
- Exercise 1에 나왔던 taper effect가 정확이 무엇을 의미하는 건지 확실치 않은 것 같다.
공부하면서 들었던 생각:
오늘 배웠던 내용은 정말 새로웠던것 같다. 코드를 이러한 방식으로 쓰니 정말 이런 방법이 있었다고?라고 할만하게 보다 직관적으로 쓰는 방법을 알아내어 기분이 좋았다. 이번 강의의 근본 토픽은 relpointbbox()의 관한 내용이었지만 code를 어떻게 보다 더욱 직관적으로 쓰고 fx방식처럼 쓸지에 대해 알아보는 시간에 더욱 중점을 맞추었던 것 같다. 또한 relpointbbox()를 통해 chramp()를 적용할때 어떻게 하여 1보다 사이즈가 큰 geometry에서 반복적이지 않은 Ramp의 형상을 그대로 구현하는데 있어 드디어 궁금증을 풀었던것 같다. 또한 이번 강의는 코드를 설명하는데 있어 지난번보다 러프 하게 진행되었던것 같다. 마치 우리가 이미 쌓아왔던것을 굳이 하나하나 기초적으로 상기 시켜주지 않았던 것은 나에게 있어 정말 큰 기쁨으로 다가왔던 것같다. TWA님께서 굳이 한줄 한줄 설명해 주지 않아도 내가 기본적으로 다 알아듣게 된다는 사실이 그래도 내가 올바른 길로 향하고 있구나 라는 생각을 조금이나마 할 수 있어서 좋았다. 이번 강의를 기점으로 이제 Joy of Vex코스 반을 지나면서 점점 이 코스의 중상급으로 입문한다는 기분이 약간이나마 든다. 이제부터 시작이겠지만 포기는 절대 하면 안된다는 생각이 든다.
'FX > Houdini_Joy of VEX' 카테고리의 다른 글
Joy of Vex - Recap of Week 3 (0) | 2022.07.11 |
---|---|
Joy of Vex - Day 11: if statements (0) | 2022.07.08 |
Joy of Vex - Day 9-2: dot and cross product, fake lighting combing normals to a surface, vector maths primer (0) | 2022.07.06 |
Joy of Vex - Day 9-1: normalize(), dot(), and cross() (0) | 2022.07.05 |
Joy of Vex - Assignment #1 (0) | 2022.07.03 |