중요했던 부분:
- vector
방향과 크기를 가지는 값. 후디니에서 말하는 Vector는 위치정보를 하나를 가지고 있지만 만약 그때 방향과 크기를 논하고 싶다면 원점을 기준으로 본 방향과 크기가 될 것이다.
- normalize(): Normalize Function
방향은 같지만 크기가 1인 벡터값으로 전환됨. normalize()은 vector의 값을 인풋으로 지정함으로써 결과값으로 vector값을 내보낸다.
원점으로부터 위치벡터를 동일한 방향으로의 크기 1짜리가 있도록 변환하는 function
v@A = @P; // @P (포인트 위치값)을 vector attribute A에 저장
v@a = normalize (@A); // 원점으로부터 방향은 같지만 크기가 1인 vector a를 vector attribute a에 저장
addpoint (0, @a); // 방금전 생성한 vector attribute a를 포인트로 생성
// run over가 Detail (Only Once)인 상황에서
vector new = {0, 1, 0}; // vector값 (0, 1, 0)을 vector variable new 에 저장
addpoint (0, add); /* 위에서 생성한 vector값의 위치를 가진 포인트를 생성, 그대신 모든 포인트에 대하여
생성이므로 run over가 point로 설정되있을시 기존 Geometry에 두 개의 포인트가 뜬다. 그러므로 한 개의 포인트
만 추가하기 위한 방법으로는 run over를 Detail (Only Once)로 바꿔 Detail Wrangle상에서 point가 하나가
생성되게끔 하여라. 그러면 기존에 있던 포인트들중 하나만 택하여 한번만 생성되게끔 한다.*/
만약 기존 geometry가 Detail Wrangle Node의 두번째 (1번) 인풋에 들어갈때는 기존 geometry가 point()로 불러져 그점들을 다시 addpoint()로 생성하지 않는 이상 불러와지질 않으므로 새롭게 addpoint()로만 생성된 점만 scene view에서 나타낸다.
// input에 연결된 geometry의 0과 1번점의 @P(포인트 위치)를 불러와라
// base (시작점) = (0, 0, 0);
// target (끝점) = (5, 0, 0);
vector base = point (1, "P", 0);
vector target = point (1, "P", 1);
vector dir = target - base; /* 아까 만들어둔 vector variable target과 base의 차를 구하여
vector variable dir 에 저장하라. 이는 base가 target으로 향하는 방향값 즉 vector값을 알려줌.
eg) if target = (5, 0, 0) and base = (0, 0, 0); 이라면 , dir = (5, 0, 0)이된다.*/
// dir에 normalize() 하여 원점으로부터 1의 크기를 가진 vector값으로 전환하여라
vector normDir = normalize (dir);
/*base로부터 normDir의 vector값을 더한값을 vector variable newPoint에 저장. 이는 새롭게
normalize()가 적용되어 나타난 값을 시작점에 더해줌으로써 새롭게 업데이트된 시작점을 나타내준다*/
vector newPoint = base + normDir;
/* 마찬가지로 target으로부터 normDir의 vector값을 뺀값을 vector variable newPoint에 저장. 이는 새롭게
normalize()가 적용되어 나타난 값을 끝점에 더해줌으로써 새롭게 업데이트된 끝점을 나타내준다*/
vector newSecond = target - normDir;
// 새롭게 만든 시작점과 끝점을 point로 다시 생성해주면서 새로운 값을 보여주어라
addpoint (0, newPoint);
addpoint (0, newSecond);
/* 방금전 선언한 코드에서 이렇게 새로운 끝점의 위치인 vector variable newSecond를 chf()같은 것을 이용해
유저가 직접 파라미터로 조절할수 있게한다면 더욱 곱해지는 chf()값이 늘어날수록 포인트는 왼쪽으로 가게된다. 왜냐하면
빼는 값이 커지게됨으로 저절로 vector값이 낮아지기 때문이다. */
vector newSecond = target - (normDir*chf ("NEWSECOND");
위치값을 x/y/z방향 어느곳에서도 적용하더라도 normalize()는 동일하게 작동한다. 즉 위와같은 직선이아닌 대각선이나 수직이여도 normalize()로 인해 vector값이 1로 조정이 가능케된다.
- Carve (First U & Second U)
조절할 수 있는 파라미터를 0에서 1까지의 range로 조절 할 수 있게함.
- cross(): Cross Function
두 벡터가 공유하고 있는 평면에 수직이 되는 방향으로 벡터값을 돌려받는다. 이때의 벡터의 크기는 cross에 들어가는 두 vector input들로 만들어진 평행사변형의 넓이값으로 결과값의 길이값으로 표현이 된다. 이때 이 vector들의 구분을 손가락으로 구분 가능한데 마치 플레밍의 오른손 법칙과 유사하다. cross()는 두 vector의 값들을 인풋으로 지정함으로써 결과값으로 vector값을 내보낸다.
cross()로 얻은 값은 우리가 지금까지 공부해왔던 한 면의 수직방향으로써 @N (Normal)의 결과값으로 나타난다.
- dot(): Dot Function
두 벡터가 있을때 그 사이 각도를 내보낸다. 이는 수학에서 내적으로도 알려져 있으며 dot()은 두 vector의 값들을 인풋으로 지정함으로써 결과값으로 float값을 내보낸다.
a*b = |a|*|b|*cos(θ) // 두 개의 vector input값들은 그 vector값들의 크기값과 cos(θ)의 곱한값과 같다.
*여기서 |a|는 vector값의 크기를 나타낸다, normalize()를 적용하면 무조건 1이됨
이라는 식으로 작동되며 a와 b의 순서와 상관없이 값을 얻어낼 수 있다.
a*b를 구하기 위해선 이와 같은 방식으로 가능하다.
eg) a = (3, 0, 4), b = (2, 0, 1)
a*b
= AxBx + AyBy + AzBz
= 6 + 0 + 4 = 10으로 결과가 나타난다. 하지만 이렇게 나타난 결과는 큰 의미를 두지 않는다. normalize()가 생략되어 값이 너무 크게 나타남으로 정확히 각도의 수치를 알 수 없다.
*normalize()*를 통해 vector값들을 다 1로 지정해주고 그 값을 내적식에 적용하였을때
a*b = |a|*|b|*cos(θ)
= 1*1*cos(θ) // normalize()를 통해 크기값이 다 1로 지정된 vector값이 됨.
= cos(θ) // 만약 cos(θ) = 0.3이라면 Cosine Function에서 높이 Y값이 0.3일때 X값 즉 90도보다 살짝 작은 값이거나 270보다 살짝 큰 값이라는 사실을 유추할 수 있다.
즉 우리가 이용한 두 vector의 normalize()가 된 vector 수치들이 있다면 dot()을 활용해서 각도를 얻어낼 수 있다.
// dot()의 과정을 vex의 형태로 적어내었을때
dot (a, b) = length (a)*length (b)*cos(θ);
// 만약 vector A와 B의 정보가 있는 상태에서
vector = A, B;
// 위의 A와 B의 vector값들을 dot()으로 각도를 얻어낼 수 있게 normalize()를 적용한다
vector a = normalize (A);
vector b = normalize (B);
// dot()을 이용해 두 vector사이의 각도를 얻어낸 값을 float variable value에 저장한다
float value = dot (a, b);
f@value = value; // float variable value의 수치를 geometry spreadsheet에 디스플레이한다
- Houdini <Light> 빛에 대한 Computing
*두 vector input값들에 normalize()가 적용됬다는 가정하에* cos(θ)는 마치 빛이 얼마나 영향을 줄지에 대해 즉 밝기에 대해 표현하고 있다. 두 input vector값들의 각도 값이 작을수록 밝기가 높아지고 각도값이 커질수록 밝기가 낮아진다. 이는 마치 빚의 산란을 연상시키며 마치 빛이 물체에 맞고 튕겨져 나올때 들어왔던 방향과 각도가 작을수록 물체에 반사되는 빛이 직빵으로오고 반대로 각도가 클 수록 물체에서 반사되는 빛이 약해지는 느낌을 준다. 즉 cosine graph를 따라 위의 설명과 같이 1에서 -1사이의 의미있는 정보를 얻어낼 수 있다.
1. 물체의 포인트들에서 light으로 향한 값들을 vector값으로 구해주고
2. 물체의 중심에서부터 포인트까지 향한 값들을 cross()로 수직인 즉 Normal값들을 구할 수 있고
3. 그렇게 구한 vector 값들을 normalize()를 적용하여 크기를 1로 만들어주어
4. 그 값들을 dot()을 통해 두 vector값사이의 각도를 얻어낼 수 있다.
이해가 안되었던 부분:
- TWA선생님께서 설명을 너무 잘해주셔서 이번엔 어려웠던 부분이 많이 없던 것 같다. 수학을 좋아한편은 아니라 생각했는데 그래도 오랜만에 다시 배워보니까 재미가 있었던것 같다. 문제는 이 방식을 이용해서 어떻게 응용하고 코드가 많아질 때 이것들을 하나하나 어떻게 꾸려 나가가고 해석을 해야할 지 많은 연습이 필요하다는 것을 느꼈다. 이 부분에 대해선 본강의를 봐야 할 것 같다.
공부하면서 들었던 생각:
이번 수업은 약간 본강의에 들어가기 앞서 function들의 대한 간략한 소개인것 같았다. 아마 이번에는 기초만 다루어 쉽게 느껴졌던것같은데 이 function들을 이제 비주얼적으로 응용하여 어떠한 모양을 생성할 수 있는지 깊게 배우는 과정이 어려워질 것같다. 그리고 이번강의는 무엇보다도 수학과 물리에 대해 많이 배운것 같고 학창시절때 배웠던 몇가지가 떠올라 약간의 추억이 생겼던것 같다. 그리고 이런게 후디니에서 적용될수 있구나라는 것에 감탄을 하게 되었다. VFX 특히 후디니를 처음 배우기 시작할때 물리의 상식이 필요하다고 해서 설마 물리나 수학 법칙이 이분야에서도 접목이 될까라는 생각을 하게됬었다. 특히나 OpenGL같은 컴퓨터 그래픽스 엔지니어링쪽으로 빠지는 것도 아닌데 말이다. 근데 이렇게 물론 수학적으론 기본들이겠지만 어쨌든 접목이 되다니 새삼 후디니라는 프로그램이 대단하게 느껴졌던것 같다. 또 강의에서 보았던 너무 리얼한 파도모양 grid와 그위에 rubbertoy 여러개가 떠있는 걸 보니 너무 멋있게 느껴졌었다. 선생님께서 이런작업을 할 날이 오실거라는 말이 또 자극이 되었던것같다. 마치 영화에서 보던 파도 모양들을 내가 구현할 거라니 더욱 포기하면 안되겠다는 생각이 든다. 더욱 본강의가 기대되게 만들어주는 이번 강의였던것 같다.