작업/작업일지

23년 12월 1주차_후디니 첫 작업물

석류! 2023. 12. 5. 08:35

 

https://www.udemy.com/course/game-asset-creation-with-houdini-f/

 

이번에 후디니를 유투브를 통해 기본지식을 배워보고

제대로 한번 입문해서 혼자서 뭘 해볼 베이스는 한번 쌓아보자 라는 마음으로..

다음강의를 듣게 되었음

마침 유데미에서 블프 할인도 했었고

2주동안 진짜 열심히 강의만 들으면서.. 

미친듯이 달리면서 강의 끝까지들어 결과물 뽑아봄

 

 

최종 결과물!

이 간단해보이는 에셋조차도.. 너무나도 많은 기능들을 필요로 했고

정말 별거아닌것같음에도 불구하고 정말 많은 코딩기술이.. 필요했었다

진짜 말도안됨...

그래도.. 제대로 다루기만 한다면 강력할듯

 

일단.. 굉장히 복잡하고 너무나도 어려웠기때문에

한번 정리하는 글을 적고 가보자 함.. 2주짜리

 

 

 

 

기본적으로 베이스가 되어줄 라인을 만들어줌

커브를 통해 제작해도 되고 편한 수정을 위해 Add 노드로 직접 위치를 이어줌

 

 

그렇게 만들어진 라인들을 균등하게 나누어 주기 위해

Fuse 노드를 이용해 끊어진 라인을 이어주고

Resample 노드를 이용해 균등하게 끊어줌

 

이제 여기서 추가를 해주었던 것이 크게

 

01. 벽 시스템

 

02. 기둥

 

03. 랜덤 창문 배치

 

04. 옥상

05. 옥상 오브젝트 랜덤 배치

06. 옥상 난간 배치

 

크게 이렇게 나뉘어져있다.

이제 각각 하나하나 살펴보자면...

 

 

 

 

 

01. 벽 시스템

몇층인지에 따라 바닥면을 Copy 노드를 통해 복사해준다.

이때 Total Number(층수) 와 Translate(높이)를 컨트롤러 파라미터와 연결해준다

 

 

 

이제 이를 For each primitive 를 이용해 프리미티브를 각각 적용해주기 위해 나누어주고

Transform 노드를 이용해 각 층의 높이만큼 Y를 변화시켜 Skin으로 이어준다

 

단순히 벽면을 만들기 위해서라면 나누어 줄 필요는 없으나

각 벽면마다 파트별로 나누어주어 그 포인트마다 랜덤으로 창문, 프랍 등을 배치하기위해

이처럼 나누어주었다

 

이때 Attribwrangle 노드에 이와같은 코드를 입력해 미리 UV를 나누어준다

 

이를 이어줬으면 뒤집혀있을때 리버스를 한번 먹여주고

Control 노드에 문의 위치(나중에 설명) 를 표현해줄

Face 번호를 pattern에 넣어 미리 삭제시켜준다

 

 

 

이렇게 벽면을 우선 제작해준다.

 

 

 

 

02. 기둥

이전의 Copy노드를 끌어와 연결해주고

이번에도 Each For Primitive를 연결해준다

 

이제 각 포인트에 Line을 연결해줄텐데

이때 기본적으로 그냥 생성된 포인트에겐 노말방향이 정해져 있기 않기 때문에

방향성을 의미해줄 노말을 @N(노말을) = set(1,0,0) 으로 설정해준다

 

 

( 이때 라인이 기본적으로 위쪽을 향하고 있는것을 사용했는데

 

이는 이 라인의 방향이 위로 향하고 있는 것이 아니다.

(0,0,0) 과 (0,1,0) 을 이어주는 Line 이 

코드로 작성한것처럼 

(0,0,0)을 기준으로 (1,0,0) 방향으로 나아가는 노말 방향으로 

라인을 배치해 줄 뿐이다.....

...  )

 

진짜... 후디니하려면...

알아둬야하는 기본 베이스 지식이....

너무나도 깊다.........

이건 더이상 아트의 영역이 아니야....

 

 

이에 따라 만들어진 라인에

Grid - Sweep 노드를 이용하여

Grid를 라인(커브)를 따라서 이어주게된다

 

 

이를 테두리 부분에도 똑같이 적용해둔다

 

이때 Resample을 추가하여 면을 몇번 끊어주었는데

꼭짓점 부분이 수평이 아닌곳이 있을때 UV가 늘어나는 경우가 있는데

이를 라인을 추가하여 늘어지게되는 부분을 제어한다

 

 

이를 합쳐 기둥부분을 제작한다.

 

 

 

 

 

03. 랜덤 창문 배치

 

 

랜덤 창분 배치 파트...

이 파트중에서 가장 어렵고 복잡했던 부분중 하나...

 

 

 

 

일단은 창문을 배치하기 위해선 각 Face 부분의 중심점을 사용하기 위해 추출하는 과정을 거친다

 

 

 

 

 

각 라인의 중심을 뽑아내기 위해

Resample 노드를 이용해 Segment를 2로 나누어 중심점을 뽑아낸다

 

생성된 포인트는 number 2 이므로

delete를 이용해 2를 제외한 다른 노드를 제거한다

 

 

이제 Face의 높이값이 Controler에 지정된 높이값의 /2 이므로

@P  =+  높이값/2

코드를 넣어준다

 

 

 

그럼 이번 과정을 통해서 각 Face의 중앙값을 뽑아낼 수 있다

 

 

이제다시 For each primitive 를 연결해준다.

 

 

 

 

 

이제 다음의 과정을 거쳐야하는데.............

여기서 For each primitive에서의 Create Meta Import Node 의 기능을 알아야하는데

 

 

 

 

이제 이 기능을 현재로썬 Detail , Iteration 을 추출해서 사용하고있는데

이제 froeach_begin 에서 받아주는 오리지날 오브젝트로부터 다음과 같이 코드를 작성해주면

 

0번 포인트에 각기 다른 번호를 넣어줄 수 있다

이게 무슨뜻이냐

 

0번 포인트에는 0 이라는 변수를

1번 포인트에는 1 이라는 변수를 넣어줄 수 있다

 

이걸 굳이  Create Meta Import Node  노드를 사용하지 않고 사용하려고 한다면 문제가 생긴다

 

foreach노드를 사용했을때

0번에게는 포인트가 1개씩 따로따로 설정되니 사진의 포인트넘버가 0

1번에게도 포인트가 1개씩 따로따로 설정되니 사진의 포인트넘버가 0

2번에게도 포인트가 1개씩 따로따로 설정되니 사진의 포인트넘버가 0

 

즉 각기 포인트에게 각기 다른 변수를 만들어 낼 수가 없다

 

그렇다면 미리 각 포인트에 해당되는 포인트넘버를 각각의 포인트에 집어넣게된다면

각 포인트마다 변수를 따로따로 넣어줄 수 있다

 

 

처음접하면 굉장히 어려운 부분이니..  이해하기위해 노력.... 이 아닌

이해가 될때까지 고통받아보자

 

 

여기서 attribute Wrangle 노드를 사용하면 각 포인트에 iter 변수를 넣어줄 수도 있는데

굳이 For each 노드를 사용하지 않고 하면안되나? 라는 생각이 떠올랐기에

직접 실험을 해봤는데

 

 

각각의 포인트에 변수는 제대로 지정이 되었다

다만 Copy to 노드가 변수값에 따라 Switch 에 넣어질 변수가 따로 적용되는것이 아닌

 

예를들어 2번째 연결된 것을 집어 넣어라 라고 작동이 되었다면

모든곳에 2번쨰 연결된 것을 집어넣게 되는 결과를 낳는다

 

그렇기에 For Each 노드가 사용되는것이고

그에따라 변수를 각기 다르게 넣기위해 Create Meta Import Node 가 사용되는것이다

물론 여기선 Iter만 사용되었기에 다른 기능들을 사용하기 위해서도 이 기능을 추가적으로 사용될 것이다.

 

 

 

그럼 이제 코드를 뜯어보자면...

 

 

일단 각 포인트에 배치해줄 창문, 창문프랍 개수를 변수로 지정하기 위해

Numinput 과 Numpropinput 변수 이름을 지정해준다

이제 그 변수값에는 현재 노드와 연결되어있는 Switch 노드를 opninput을 이용해 적어준다

 

Opninput 은 연결된 노드 값을 변수로 가져온다.

 

 

먼저 int iter = detail(1,"iteration",0)+1; 를 통해  각 포인트에 맞는 변수를 저장한다

이때 여기에 우리는 다른 변수인 0~1 를 곱해줄 것이기떄문에 0에 곱해버리면 0과 가까운 int가

다른것에 비해 빈도가 많아지므로 1을 더해준다

 

 

이제 어떤 창문종류 , 창문프랍종류 를 정해주기 위해

랜덤값 ( 0 ~ 1 ) * 종류 수  를 만들어 주기 위해

랜덤값에는 rand ( iteration * Seed(조정가능한임의변수) ) 을 통해

rand 안에 값에는 컨트롤러로 조절하는 Seed 값 * 각 변수의 번호 iter ( 각기 다른변수를 주기 위해 )

를 넣어 각각 ( 0 ~ 1 ) 의 랜덤값을 지정해준다

 

이제 이를 이용해 각기 다른 변수를 지정해주고

컨트롤러로 조정가능한 int == 자신의 포인트넘버 ( iter ) 코드를 넣어주어

하나의 변수에 문이 들어가게끔 코드를 짜준다

 

if(iter == ch("../../buildingbuilder_01/Door_Prim"))
    {
        @group_Window = 0;
        @group_Door = 1;  
    }
    

 

그렇게 다음과 같이 각각 다른 창문을 넣어줄 수 있다

 

 

 

 

 

 

 

 

 

 

04. 옥상

 

 

 

옥상부분 또한 이전 창문배치하듯이 각 부분을 나누어주고 중심값을 추출해 그에 맞게 배치할 예정이다.

그렇기에 divide 노드를 통해 1 값으로 나누어준다.

 

이때 1로 나누었을때 제대로 나누어지지 않는다면.. 

0.9999로 나누어 준 후 Clean으로 적절하지 않은 포인트들을

반올림을 통해 각 값을 다시 정수로 변환하여 사용해 주도록 하자

 

 

 

그 뒤로는 이전처럼 중앙값을 뽑는 코드인데....

 

 

 

 

......

..

..

난 아직도 이 코드가 도대체 어떻게 작동하는지 잘 모르겠다....

이 코드로 중앙값을 뽑아주도록하자....

 

 

 

 

 

마무리가 되었으면 이전에 했던것과 비슷하게 코드를 작성해준다

 

 

 

fit 는

fit ( @변수 , 최소값 , 최대값 , 최소값이하일때 이만큼 적용 , 최대값이상일때 이만큼 적용 )

으로 보면 된다

 

이때 @변수에는 컨트롤러로 조절해도되고 $F 같은것을 넣어도 작동된다

 

 

 

quaternion 코드는...

.....

...

..

..

..

 

여전히 모르겠다

여기 이해할때랑 For each 에서의  Create Meta Import Node 사용할때가 가장 이해가안됐다

 

 

 

 

 

 

 

 

06. 옥상 난간 배치

 

 

마지막인 난간 배치노드

여기에서는 굉장히 꼬여있고 많은 기능을 넣었기에 subnet으로 넣어주었다

 

 

 

 

이제 라인을 Carve 노드로 각 포인트경계로 한번 끊어주고

거기에서 한번더 Carve를 넣어 서로 반대편에서 같은값만큼 수치가 변하도록

컨트톨러로 작동시키도록 파라미터를 넣어준다.

 

 

 

이를 resample 로 나누어주고

노말값을 다시금 지정해준다.

 

 

이를 copy to point로 라인들을 배치해주고

이를 grid 와 sweep 노드로 연결해준다

( 그냥 sweep 연결해도 잘 작동한다 )

 

 

 

 

 

 

이제 난간 중 손에 닿는곳을 각자 알잘딱해서 만들어주고

 

 

 

Polyframe 으로 방향있는 노말값을 만들어주고

 

0번 포인트에게

1번째 포인트의 위치 ( 0.877 , 3.0 , 0.0 ) 에서 현재위치 ( 0.123 , 3.0 , 0.0 ) 을 빼준다

그러면 0번 포인트에게만 다음 포인트를 향하고 있는 노말값을 얻을 수 있다

 

 

 

이를 Copy To Point 노드로 옮겨주고

Add 노드로 이어준다.

 

 

 

이후 Fuse로 각 포인트들을 이어주고

clean 으로 정리를 해준다

 

( join 노드는 지금해보니 없어도 잘 작동한다 )

 

 

 

이를 grid 와 sweep 노드로 연결해준다

( 그냥 sweep 연결해도 잘 작동한다 )

 

 

 

 

 

이제 보면 한 라인에 copy to point를 넣어서 위치가 겹쳐있을텐데

transform 노드의 Y에 bbox("../ ( 기둥 최종노드 ) /",D_YSIZE)+($SIZEY/2) 를 입력한다

 

 

여기서 bbox는 한 노드의 x y z 크기을 추출해주는데

기둥의 x y z 크기 중 D_YSIZE, 즉 Y 크기값을 추출 한 뒤 

 

이러면 기둥의 맨 윗 끝부분에 겹칠테니

자신의 크기를 추출해주는 $SIZE 노드를 이용해 자신의 Y크기의 절반 ($SIZEY/2) 을 더해준다

 

 

 

이들을 전부 합쳐주면 난간 완성

 

 

이걸로 모든 파츠 완성!!!!!!!!!!

 

 

 

 

 

 

 

정말.. 이 간단한거 만드는 데에도 이렇게 많은 코드와 노드가 사용되었고....

후디니는 정말 모든게 코딩덩어리 였다.....

그 어떤 3D 기본지식을 탄탄하게 채워와도

우리는 후디니 앞에서 뉴비가 될것이며

후디니로 모든걸 할수있어요! 라는 뜻은

네놈은 후디니로 모든걸 처음부터 다뤄야 할것이다 라는 뜻이였다....

 

이걸로.. 하나 마무리 했으니....

여기서 배운 후디니 코드들을 좀 정리도 해보고

앞으로 할것들을 좀 찾아봐야겠다