중요했던 부분:
- intrinsics
intrinsics란 Geometry의 프리미티브가 가지고 있는 내재된 정보들을 의미한다. 이때 intrinsics들의 대한 정보들은 여러개가 있는데 geometry의 결과의 종류의 따라 intrinsics가 가지는 정보의 종류도 바뀌기도 한다. intrinsics의 종류들과 그의 대한 수치들을 확인하기 위해서는 primitive geometry spreadsheet -> intrinsics으로 들어가 확인가능하다.
*intrinsics들은 geometry의 따라 나타나는 종류와 구성이 전부 다르다. 그러므로 각각의 geometry의 종류에 맞추어 알맞은 intrinsics들을 적용하는 스킬을 키워야 한다*/
이때 geometry spreadsheet의 나타나는 intrinsics의 대한 수치들은 각각 회색과 흰색을 띄는데 숫자들이 흰색으로 표현된것은 바꿔줄 수 있는 정보들을 의미하는 반면 회색으로 표현된 것은 바꿔주지 못한다는 의미를 담고있다.
우선 나는 맛보기로 closed를 담당하는 intrinsic값을 geometry spreadsheet에서 찾아보기로 하였다.
intrinsic에는 여러가지의 종류들이 있는데 이번 Day 18 강의에서 배운 중요한 것들만 뽑자면 이와 같은 것들이 있었다.
bounds | bounding box가 geometry를 감싸고 있을때의 box의 최댓값을 각각 나타낸다. 총 6개의 값을 가지며 이는 각기 (x의 최소, x의 최대, y의 최소, y의 최대, z의 최소, z의 최대)를 나타낸다. |
measuredarea | 특정 geometry에서 각각의 primitive의 면적들을 나타낸다. 총 하나의 값만을 가지는 것이 특징이다. |
closed | geometry의 primitive가 막혀있을때 0 그리고 뚫려있을때 1을 나타내므로써 하나의 값만을 가진다. |
transform | 3*3 matrix의 정보로써 geometry의 형태모양의 수치상을 나타낸다. 이는 rotation, scale & shear값들이 조합된 비율의 형태이다. 그래서 총 9개의 값들을 가진다. |
- pack (Node)
pack node는 특정 geometry의 대해 여러개의 포인트나 프리미티브로 구성되어져 있을때 연결해주면 오직 하나의 포인트와 프리미티브로써 구성되게끔 만들어주는 node이다.
- primintrinsic (): Primitive Intrinsic Function
primintrinsic()은 intrinsic의 정보를 vex에서 읽어서 불러올수 있게 하는 function으로 특정 intrinsics의 값들에 포인트를 생성해주거나 무엇을 하려고자 할때 이 function을 이용해서 vex로 이용할 수 있다. 이때 input으로는 wrangle노드에 연결된 input넘버, 불러오고자 하는 intrinsic의 종류, 그리고 몇번째 프리미티브의 대한 정보를 불러올것인지의 대한 프리미티브 넘버를 입력하면 된다. 이렇게만 보면 마치 point() 내지는 primitive() (안배워서 있는지는 모르겠다. 근데 아마 point()와 동일하게 primitive를 특정 wrangle노드에 불러오는것으로 작동되는 function은 무조건 있을거라 생각한다) 와 동일한 원리를 기반으로 작동되는 것을 확인할 수 있다.
/* 이때 addpoint()로 만드는 포인트는 기존에 연결된 geometry의 포인트의 대해서 만드는 것이 아니라 bounding box의
정보를 따라 설정해주는 것이기 때문에 wrangle노드를 detail(only once)로 설정해주었다*/
/* 앞서 설명했듯이 primintrinsic()을 활용하여 1번 인풋에 연결된 Geometry의 0번 포인트의 bound intrinsic
정보를 불러와 float array variable bounds에 저장하여라. 이는 bounds가 값을 6개 가지기 때문에 여러개의
값들을 담을 수 잇는 array로써 저장하였다.*/
float bounds[] = primintrinsic (1, "bounds", 0);
// 각기 array안에 있는 수치들을 나누어 각각의 6개의 variable들로 나누어주었다.
float xmin = bounds[0];
float xmax = bounds[1];
float ymin = bounds[2];
float ymax = bounds[3];
float zmin = bounds[4];
float zmax = bounds[5];
/* 이때 addpoint()를 사용하여 3d상의 위치에 포인트들을 생성해주기 위해 위에서 만든 각기의 float값들을
조합하여 vector값으로 만들어 주어 포인트들이 각기 다른 위치 즉 bounding box를 이루는 포인트들의 위치에
위치하도록 세팅해주었다.*/
vector p0 = set (xmin, ymin, zmin);
vector p1 = set (xmin, ymin, zmax);
vector p2 = set (xmin, ymax, zmin);
vector p3 = set (xmax, ymin, zmin);
vector p4 = set (xmax, ymin, zmax);
vector p5 = set (xmin, ymax, zmax);
vector p6 = set (xmax, ymax, zmin);
vector p7 = set (xmax, ymax, zmax);
// 위에서 만든 총 8개의 vector값에 포인트들이 각기 위치하도록 addpoint()를 사용하여 point를 생성해주었다.
addpoint (0, p0);
addpoint (0, p1);
addpoint (0, p2);
addpoint (0, p3);
addpoint (0, p4);
addpoint (0, p5);
addpoint (0, p6);
addpoint (0, p7);
위의 정보를 활용하여 이렇게 sphere를 감싸는 bounding box를 이루는 포인트들의 vector위치에 임의적으로 point들을 addpoint()로 생성해주어 아래와 같은 결과를 만들어 보았다.
그래서 이와 같이 동일한 코드를 geometry에 붙여도 Geometry가 다르게 생기고 그로인해 bounding box의 쉐입또한 바뀌게 되면 addpoint()로 생성된 point들의 위치들 또한 알맞게 바뀌는 것을 알 수 있다.
이때 pighead에도 똑같이 만들어고자 하였는데 이때 pack을 사용하여 geometry의 primitive갯수가 오직 하나만 있도록 해주었다. 이때 안 사실은 primintrinsic()에서 세번째 정보를 0으로 설정해주었기 때문에 오직 0번 프리미티브의 대한 bounds값을 가져온다. 그러므로 geometry를 이루는 primitive의 갯수가 0번 프리미티브 오직 하나여만 제대로 bounding box의 bounds수치들 불러올 수 있기 때문에 아래와 같이 pack노드가 연결된 pighead에서 정확히 잘 코드가 적용되도록 하였다.
이때 bounds뿐만아니라 다른 intrinsic을 불러올 수 있는데 나는 measuredarea를 불러와 특정 프리미티브의 넓이값을 vex로 불러오기로 하였다. 우선 grid를 사용하여 grid의 하나의 primitive만 edit을 사용하여 기형적으로 만들어 준 다음 모든 프리미티브의 면적을 불러와 지정한 attribute에 저장해주었다.
/* primintrinsic()을 사용하여 0번 인풋으로 연결된 geometry의 @primnum값에 해당하는 (즉 모든 primitive를 각기 불러와서)
프리미티브의 measuredarea값 (프리미티브의 넓이 값)을 불러와 f@area로 저장하여라 */
f@area = primintrinsic (0, "measuredarea", @primnum);
// 만약 프리미티브의 면적갑이 chf()로 지정된 A값보다 작다면 파란색으로 표시하여라
if (@area < chf ("A")) {
@Cd = {0, 0, 1};
} else { // 그렇지 않은 부분은 전부 노란색으로 표시하여라
@Cd = {1, 1, 0};
}
위와 같은 vex code를 사용하여 아래와 같이 파라미터로 지정된 A값보다 작은 primitive의 면적을 가진 Primitive는 파란색으로 설정되게끔 나머지는 노란색이 되게끔 설정해주었다.
- setprimintrinsic (): Set Primitive Intrinsic Function
setprimintrinsic()은 정보를 읽어서 코드로 불러오기만했던 primintrinsic()과는 다르게 primitive의 대한 intrinsic값을 직접 수정하거나 써넣어줄 수 있다. 이때 geometry spreadsheet상에서 하얀색으로 적혀있는 intrinsic값들만 이에 해당하여 값을 바꿔줄 수 있다. setprimintrinsic()의 정보들로는 wrangle노드로 연결된 인풋 넘버, 불러오고자 하는 intrinsic종류, 바꾸고자 하는 primitive넘버, 그리고 수정하려고자 하는 값으로 입력해줄 수 있다.
// integer variable a는 0으로써 지정해준다
int a = 0;
/* setprimintrinsic()을 사용하여 0번 인풋으로 연결된 geometry에서 2번 프리미티브의 closed intrinsic값을
방금전 지정해둔 integer variable a즉 0으로 지정해주어 막혀있던 부분을 뚫리게 만든다.*/
setprimintrinsic (0, "closed", 2, a);
/* setprimintrinsic()을 사용하여 0번 인풋으로 연결된 geometry에서 5번 프리미티브의 closed intrinsic값을
방금전 지정해둔 integer variable a즉 0으로 지정해주어 막혀있던 부분을 뚫리게 만든다.*/
setprimintrinsic (0, "closed", 5, a);
이와 같이 box상에서 2번과 5번 프리미티브의 closed여부를 0으로 바꾸어 primitive가 뚫리게끔 수정해주었다.
이때 나는 closed뿐만 아니라 transform intrinsic을 활용해 뒤틀려진 sphere를 setprimintrinsic()을 활용하여 정상적으로 구현되게끔 만들어 보았다.
이때 위에서 언급했듯이 transform intrinsic은 matrix의 수치로써 9개의 값들을 가지는데 이를 ident()을 사용하여 단위행렬로 만들어 주면 기본적인 matrix를 생성하게끔 가능하다. 그러므로 나는 아래와 같은 코드를 작성해보았다.
// ident()로 기본적인 단위행렬을 3x3 matrix의 형태로 variable m에 저장해주었다
matrix3 m = ident ();
// 0번 인풋에 연결된 Geoemtry의 0번 프리미티브의 tranform intrinsic을 불러와 m의값으로 수정해주어라
setprimintrinsic (0, "transform", 0, m);
이때 sphere를 이루는 primitive가 하나밖에 없는 primitive의 형태일때 transform intrinsic의 9개 matrix값을 단위행렬로 바꾸어 기본적인 프리미티브의 rotation, scale, 그리고 shear값을 이루게끔 설정해주었다.
또한 이렇게 각각 transform intrinsic을 유저가 파라미터로 각기 vector값으로 조절 가능하게하여 만들어 보았다. 이때 transform intrinsic은 rotation, scale, shear을 전부다 비율로써 수치로 나타냄으로 이를 조절하여 원하는 모양을 만들 수있게 해보았다.
// vector variable a, b, c값들을 만들어 주어서 chv()을 사용해서 파라미터로 조절 가능하게 하였을때
vector a, b, c;
a = chv ("A");
b = chv ("B");
c = chv ("C");
// matrix3 variable m에 vector값이 세개 들어갈 수 있도록 만들어 준다.
matrix3 m = set (a, b, c);
/* setprimintrinsic()을 활용하여 0번 인풋으로 연결된 geometry의 0번 프리미티브의 transform intrinsic
의 정보를 m의 수치로 바꿔주어라*/
setprimintrinsic (0, "transform", 0, m);
이때 만든 코드를 copy to points노드를 사용하여 copy된 geometry의 모양을 바꾸려면 어떻게 해야할까? 아마 대부분은 copytopoints노드에 연결되기 전에 해당 코드가 있는 wrangle노드를 연결하여 만들어줄 것이다. 하지만 그렇게 하면 merge로 묶어진 point들에서는 프리미티브의 intrinsics 하나도 없기 때문에 아무일도 일어나지 않는다. 그래서 copytopoints에는 프리미티브의 정보들이 각각이 있으므로 copytopoints아래에다 연결하여 copy된 geometry가 해당 코드를 수행할 수 있게끔 해주어야 한다. 또한 이때 하나의 프리미티브 즉 하나의 sphere만 효과가 먹히지 않게끔 하여 코드를 약간 수정해주었다.
// vector variable a, b, c값들을 만들어 주어서 chv()을 사용해서 파라미터로 조절 가능하게 하였을때
vector a, b, c;
a = chv ("A");
b = chv ("B");
c = chv ("C");
// matrix3 variable m에 vector값이 세개 들어갈 수 있도록 만들어 준다.
matrix3 m = set (a, b, c);
/* setprimintrinsic()을 활용하여 0번 인풋으로 연결된 geometry의 모든 프리미티브에서의 transform intrinsic
의 정보를 m의 수치로 바꿔주어라*/
setprimintrinsic (0, "transform", 0, m);
이때 setprimintrinsic()이 아닌 quaternion()과 @orient를 사용하여 sphere를 살짝 rotation시키는 것도 가능케 해보았다.
// vector variable a, b, c값들을 만들어 주어서 chv()을 사용해서 파라미터로 조절 가능하게 하였을때
vector a, b, c;
a = chv ("A");
b = chv ("B");
c = chv ("C");
// matrix3 variable m에 vector값이 세개 들어갈 수 있도록 만들어 준다.
matrix3 m = set (a, b, c);
/* matrix값을 담고있는 variable m을 @orient로 집어넣어 copy된 sphere가 파라미터의 값에 따라 rotation되도록
설정해주었다. 이때 B는 @N의 방향 그리고 C는 @up의 방향을 나타내는 것을 알 수 있다.*/
@orient = quaternion (m);
- packedfulltransform intrinsic & Simulation
packedfulltranform intrinsic은 4*4의 matrix를 가지고 있는 intrinsic들 중 하나로써 각각의 수치들은 상새한 정보들을 나타낸다. cgwiki님의 자료를 살펴보면 이러한 결과를 알 수있다. 이때 초록색값이 @orient와 quaternion()를 활용할때 무척이나 중요함으로 그 부분만 때어서 가져오는 과정은 해당 matrix에서 새롭게 matrix3(variable)으로 새롭게 type casting하여 가져올 수 있었다. 예시는 아래 코드를 참조할 수 있다.
오늘 강의에서는 특이하게 후디니1을 들어가기전 맛보기로 시뮬레이션을 어떻게 제작하는지 살짝 알려주었다. 깨진 box가 grid에 부딪히면서 와장창 조각들이 흩어지는 애니메이션으로 이 애니메이션을 통해 packedfulltranform에 대해 알 수 있었다.
우선 이와 같이 노드들을 세팅해두어 와장창 떨어지는 모션을 만들어 보았다. (오늘 강의에 있어 중요한 내용은 아니니 과정은 생략하겠다)
이때 dopimport로 dopnet에서 만들었던 모션을 아래와 같은 형태로 가져와 packed가 되어 각각의 깨진 box조각들이 하나의 프리미티브만 갖게끔 설정해주었다. 그리고 copytopoints로 rubbertoy를 연결하여 box pieces대신 rubbertoy가 대신되게끔 세팅해주었다.
근데 문제는 Rubbertoy가 떨어지는 직후 이상하게 뻉뺑돌아가다가 위로 곧두서는 것을 알 수 있었다.
이는 @orient값이 제대로 원하는대로 설정되지 않아서 막무가내로 움직이는 것이었다. 이를 보완하기 위해 packedfulltransform intrinsic에서 quaternion()이 소화할 수 있는 부분만 때어내 @orient로 보여주는 wrangle노드를 추가하여 코드를 작성해보았다.
/*primintrinsic()으로 0번 인풋에 연결된 Geometry의 @ptnum에 해당하는 모든 프리미티브들의
packedfulltransform의 정보를 불러와 matrix variable m값에 저장한다.*/
matrix M = primintrinsic (0, "packedfulltransform", @ptnum);
/* matrix4값을 가진 M값 (4x4) 을 matrix3 즉 3x3의 행렬을 가진 값으로 type cassting해주고
그 값을 matrix3 variable m에 저장. 이때 불러오는 값은 위에서 설명한 초록색값만 불러오게 할 수 있다*/
matrix3 m = matrix3 (M);
/* quaternion()에 matrix의 정보를 담고있는 variable m을 넣어주어 packedfulltransform의
정보에 따라 방향값이 정해지도록 설정*/
@orient = quaternion (m);
/* 이때 x/y/z 방향으로 각기 Rotation할 수 있게끔 설정할 수 있게 vector variable k를 만들어준다음
rand()를 이용하여 @ptnum에 따른 각기 다른 방향의 대한 random값을 지정해주었다. 또한 Radians()를 사용하여
유저가 파라미터를 조절할때 degree값으로 수정할 수있께끔 설정*/
vector k = radians (chv ("K")) * set (rand (@ptnum)-0.5, rand (@ptnum+123)-0.5, rand (@ptnum+532)-0.5)*3;
/* eulertoquaternion()을 활용하여 x/y/z값을 따로 조절하게끔 만들어 vector4 variable (임시 @orient)
new에 저장*/
vector4 new = eulertoquaternion (k, 0);
// 방금만든 quaternion()으로 만들어진 두 값들을 둘다 적용시켜주기 위해 qmultiply를 활용하여 @orient로 보여주었다.
@orient = qmultiply (@orient, new);
/*Rand()를 이용해 @ptnum에 따른 랜덤하게 만들어진 값에서 2를 나누어 random range를 반으로 나누어주고
0.4를 더해 최솟값을 0.4로 설정하여 그 값을 @pscale로 보여주어 크기로 보여주게함*/
@pscale = rand (@ptnum+chf ("SEED"))/2+0.4;
그리고 unpacked된 기존의 box 더미들을 dopimport로 불러와 material를 지정해준다음 merge로 묶어주어 아래와 같은 결과물을 완성해보았다.
Exercises:
1. What other intrinsics can you find? Check what is available on some more exotic geometry types like volumes vs vdbs, packed alembics
우선 volume노드에서 찾을수 있는 intrinsics들의 종류들은 다음과 같이 있었다. 정확히 대부분 (배운것 빼고) 무엇을 역할하는지 잘 모르겠고 문제에서도 설명하라는 말이 언급되지 않아 스크린샷으로 남겨두었다.
vdb종류가 여러개있었는데 하나를 생성해보니 느낌표가 뜨고 intrinsics들은 확인할 수 없어서 넘어가 보았다.
alembic노드에 pack노드를 연결해 pack해준상태에서 intrinsics들을 관찰해 보았더니 이와 같은 목록이 있었다.
2. We've gone through most of the common attribute types and how to define them by prefixes, search the help to find the full list
그렇다. Joy of Vex 코스를 진행하면서 거의 대부분의 흔한 attribute들은 자세하게 배웠던 것같다. 그것들이 어떠한 type인지도 알고도 말이다. 그렇다면 Full list는 어디서 확인할 수 있을까? 친절하게도 sidefx 웹사이트에 전부다 나와있어 후디니를 공부함에 있어서 이 페이지와 친숙해져야 한다는 사실을 깨달을 수 있었다.
https://www.sidefx.com/docs/houdini/model/attributes.html
Geometry attributes
Attributes are named values stored on vertices, points, primitives, and objects. Point color, position, UV coordinates , spline weight (W), and normal, for example, are stored as point attributes. Houdini sets some point attributes that you can use in expr
www.sidefx.com
지금까지 배웠던 타입들의 attribute들은 이 웹사이트에 전부 찾아볼 수 있어서 이 사이트와 친숙해져야겠다는 생각이 들었다.
3. What other intrinsics are writable?
지금까지 쓸수 있었던 intrinsics들은 closed와 transform intrinsics들이었는데 이 말고도 pivot과 pointinstancetransform 그리고 viewportlod와 같은 intrinsics들이 setprimintrinsic()과 같은 function으로 쓸 수 있다는 사실을 알게 되었다. intrinsics들의 종류가 어마어마하게 많은데 정작 쓸수 있는 것이 별로 없어서 많이 놀랬다.
4. Are there any intrinsics at other geometry levels? (Ie point intrinsics, vertex intrinsics, detail intrinsics)
point와 vertex에는 intrinsics들이 없어서 많이 놀랬다. 이는 아마 intrinsics들은 프리미티브를 주로 변형해주며 정보들을 담길때문이라고 해석하였다. detail에는 있었는데 primitive intrinsics들에 있는 것과 거의 동일한듯 아닌듯 보여졌다. 그래서 이는 다음에 더 후디니를 배우며 알아야할 숙제라고 해석하였다. 아래는 동일한 geometry에서의 각기 다른 intrinsics들의 종류들이다.
이해가 안되었던 부분:
- 4번 exercise에서 point를 담당하는 intrinsics들이나 vertex를 담당하는 intrinsics들은 찾아볼 수 없던건지 궁금하였다. 이는 아마 있는데 내가 못찾은건지 아니면 진짜로 아예 point나 vertex안에 있는 intrinsics들은 없는건지 알 수가 없었다.
- 시뮬레이션할때 dop을 구성할때 뭐가 뭔지 아무것도 몰라서 그냥 따라하기만 했다...ㅋㅋ 뭐 이것들은 나중에 후디니1에서 배울 내용같아서 걱정은 없다.
공부하면서 들었던 생각:
드디어 끝자락이 거의 온것 같다. 사실 대학교 학기도 시작하고 뒤숭숭하게 마무리를 보내는 것 같아 선생님들께 많이 죄송스럽다. 진도도 많이 밀리고 해서 조금은 죄책감? 같은것도 있는것 같다..ㅋㅋ 그래도 빨랑 완강하고 기말고사까지 이번주 안으로 처리해야겠다는 생각이 든다. intrinsics의 대한 내용들은 솔직히 지루한 면이있었던 것 같다..ㅋㅋㅋ 시뮬레이션을 하고나서 보니까 그런가.. box들의 조각들이 grid에 부딪혀 산산조각날때 처음 느끼던 그 쾌감은 정말 신기했다. 간단한 시뮬레이션이지만 내인생 최초로 후디니로 그런것을 만들어 내니 괜히 뿌듯하기도 하였다. 그래도 joy of vex를 배우니 피가되고 살이되는것을 많이 느낄것이라는 것을 안다. 다음에 배울 산더미같은 후디니 코스들도 그렇고 벌써부터도 현재 학교에서 배우기 시작한 유니티 C#프로그래밍도 후디니 vex를 공부하다보니 생각보다 공통된게 많아 신기하기도 하여 많은 도움이 되었다. 빨랑 마무리해서 twa님의 감정선 대폭발 영상을 보고싶다. 얼마나 감정선이 폭발되었을지 너무너무 궁금해서 미치겠다.
'FX > Houdini_Joy of VEX' 카테고리의 다른 글
Joy of Vex - Day 20: pointclouds, further learning (0) | 2022.08.07 |
---|---|
Joy of Vex - Day 19: primuv, xyzdist (0) | 2022.08.04 |
Joy of Vex - Day 17-2: copy sop, orient, quaternions (0) | 2022.07.31 |
Joy of Vex - Recap of Week 5 (0) | 2022.07.29 |
Joy of Vex - Day 17-1: copy sop, orient, quaternions (0) | 2022.07.27 |