본문 바로가기

Houdini/Houdini1_Starter

STARTER06_ INITIAL VALUES(FOR EACH 노드 들어가기 전에)

목차

  • 오늘의 예제
    • 점 하나로 애니메이션 만들기
    • 그리드에 적용시켜서 애니메이션 만들기
  • 일기

모든 랭글러를 위하여!

 

For each

  • 키워드 : 반복
  • VEX에서의 반복이 아닌, 노드 단위에서의 반복
  • 부족하게, 혹은 잘못 이해한 상태로 넘어가버리면 정작 써야 할 때 주어진 파라미터 하나하나 바꿔가면서 본인이 무얼 하고 있는지도 모르게 될 수 있다.

 

For each의 핵심

  • 반복에 대한 편의를 제공받는 것
  • 일단 For each 관련 노드를 바로 사용하진 않고, For each 노드가 없었다면, 어떻게 반복작업을 해줘야 했을지에 대해 짚어보고 갈 것이다.

오늘의 예제

  • 그리드의 모든 포인트에서 막대 형태의 빔이 랜덤 하게 쏘아지도록 라인 애니메이션을 작업하는 것(키프레임 사용 안 함, 솔버 활용한 결과도 아님)

 

일단 라인 애니메이션을 어떻게 구현해 줄지에 대해서 생각을 해보자.

점 하나만 가지고 일단 만들어보자.

이렇게 만들어진 점 두 개를 선으로 만들어준다.(add 사용)

그리고 Carve 노드를 달아주면, First U / Second U 값을 활용해서 라인 애니메이션을 만들어줄 수 있다.

  • (First U가 먼저 값이 증가하고, 그 뒤를 이어서 Second U의 값이 증가하는 애니메이션)

 

Wireframe Node를 달아서 라인에 두께감을 추가해 주고, Color Node를 달아서 색을 추가해 주자.

두께와 색이 추가된 라인

이제 중요한 것은 Carve에 들어갈 First U / Second U 값을 어떻게 통제할 것인지에 대한 부분이다.

  • 만들어져야 할 정보는 First U / Second U에 들어갈 값이고, 이것이 애니메이션의 핵심이다.(0 ~ 1 사이로 값이 변하는 것)
  • 어디에선가 값을 만들어내서 First U / Second U에 넣을 것인데, 그 값은 시간에 따라 0에서 1로 움직인다면, 그것이 바로 애니메이션이다.
  • 만일 어딘가에 10f에 0이고 32f에 1로 변하는 값이 있다면, 그 값을 Point function을 통해 가져와서 Carve에 활용할 수 있을 것이다.

시간에 따라 0~1 사이의 값으로 표현되는 정보를 만들어줄 것이고, 이 값으로 애니메이션이 작동할 것이다.


지금부터 아래 설명하는 내용은 매우 중요한 개념이다!!!! 꼭 이해하고 넘어가자.

 

가장 먼저 설정해줘야 할 것은 애니메이션이 몇 프레임에서 시작할지(시작 프레임), 그리고 몇 프레임에서 끝이 날지(끝 프레임)를 정해주는 것이다.

 

i@SF; // start frame

i@EF; // end frame

 

그리고 float attribute를 하나 생성할 것이다. 

 

f@play; // animation rate

 

play라는 어트리뷰트는 0~1 사이의 값을 가지게 할 것이고, 임의의 시작프레임 이전에는 0으로 값이 유지되다가 시작프레임부터 0으로 시작해서 임의의 끝 프레임까지 1로 증가하고, 끝 프레임 이후부터는 1로 유지되도록 할 것이다. (clamp, fit이 생각난다)

@play = 0.8; // 애니메이션의 진행도가 80% 임을 의미한다.

@play = 0.17; // 애니메이션의 진행도가 18% 임을 의미한다.

 

조건문을 만들어주자.

@play = 시작 프레임 전에는 0, 끝 프레임 이후는 1

시작프레임과 끝프레임 사이의 임의의 현재 프레임에 대해서 비율(@play)을 어찌 알 수 있을까?

play 어트리뷰트가 변하기 원하는 전체 간격은 @EF - @SF로 나타낼 수 있을 것이다(끝 프레임 - 시작 프레임)

그리고, 현재의 프레임의 비율은 @Frame - @SF(현재 프레임 - 시작 프레임)를 전체 간격으로 나눠줌으로 알 수 있을 것이다.

ex) @SF = 10, @EF = 42, @Frame = 18이라면, (18 - 10) / (42 - 10) = 8 / 32 = 1 / 4 = 0.25 (0 ~ 1 사이의 값을 얻을 수 있다)

SF / EF 는 현재 임의의 값

이렇게 만들어준 play 어트리뷰트는 Carve에 Point expression function을 이용해 불러온다.

해석은 다들 가능하실테니까 생략 :)

 

※ 이 개념, 굉장히 중요하다. 이 방법은 key frame을 이용하지 않았지만, key frame의 핵심 개념인, frame에 따른 값의 변화를 동일하게 구현해 준 것이다.

 

더미 데이터로 넣어두었던 @SF, @EF를 channel function을 활용해서 변경이 가능하도록 만들어주자.

 

지금까지 만들어준 @play 값은 linear 한 결과를 반환하고 있다.(등속운동)

이 값에 대해 channel ramp를 활용해 주자.

지금은 이전의 @play와 별 차이가 없다.

@play = chramp("TWA", @play);

// play 어트리뷰트를 갱신할 것이다. 채널 램프를 활용해서, 그 채널 램프의 이름은 TWA이고, 앞서 받았던 @play를 활용해서 새로운 @play를 만들어준다.

 

만약 현재상황에서 Second U보다 First U가 커지는 상황이 온다면, 우리가 만들려는 애니메이션은 뒤집혀버리는 현상이 일어날 것이다.

 

First U를 항상 Second U보다 작아지도록 채널 램프를 활용해서 만들어보자.

 

우린 현재

  • 포인트 하나를 가지고 애니메이션을 만들었다.
  • 처음 시작할 때, (0,0,0)에서 시작을 했다.
  • 애니메이션의 목표지점이 될 점을 만들었다.
  • 그 둘을 가지고 선으로 표현해 주고, Carve 노드를 활용해서 선에 애니메이션을 줄 수 있음을 확인했다.
  • 그리고, 애니메이션이 언제 시작할지(스타트 프레임)에 대한 이야기를 했고, 애니메이션이 언제 끝날지(엔드 프레임)에 대한 이야기를 하였다.
  • 스타트 프레임과 엔드 프레임 사이에 어떤 일이 일어날지, 그것에 대한 표현을 위해 @play를 만들었다.
  • 이때 스타트 프레임보다 작은 구간은 @play 값이 0이었고, 스타트 프레임과 엔드 프레임 사이에서는 0 ~ 1 사이의 소수값으로 표현되었으며, 엔드 프레임보다 큰 구간은 @play 값은 1이었다.
  • 그다음, Carve에 first U / second U 값이 필요했기 때문에 그에 대한 정의를 내려주었다.
  • 그리고 그렇게 정의 내린 두 값은 point function을 활용해서 Carve node에 불러왔다.

지금부터의 키워드는 '얼마나 무작위로 작업이 될 것인가'이다.

 

현재까지의 작업을 9개의 점을 가진 Grid를 가지고 각 포인트마다 반복한다 했을 때의 결과는 다음과 같다.

각 포인트에 대해 모두 같은 값을 가지게 될 것이다.(우리가 원한 결과는 아니다)

우리가 원하는 것은 For each 안에서 이 작업이 이뤄질 때, 0번 포인트부터 8번 포인트까지 높이, SF, EF가 다 달랐으면 하는 것이다.(무작위성)

 

랜덤 한 결과를 만들어내기 위해서 Seed를 만들어줄 것이다.

우리가 Seed를 만들어서 배정을 하더라도, 완벽한 무작위 수를 넣을 수는 없다. 왜냐하면 한계가 존재하기 때문이다. (높이는 마이너스 값이 나오면 안 되고, 우리가 대략적으로 바라는 높이와 시간의 한계 또한 존재한다. - 오차의 범위를 우리가 정해줄 수 있어야 한다)

 

아이디어)

  • rand function을 활용하여 Seed Attribute를 만든다.
  • rand function은 각 포인트마다 다르게 생성하기 위하여 ptnum을 활용한다.(rand(@ptnum))
  • ptnum이 같을 경우엔 rand function을 사용한다고 해도 seed 값이 똑같기 때문에 같은 포인트 넘버를 가진 포인트에서는 같은 결과를 반환해 준다. 이런 것을 방지하기 위해서 rand function의 seed에 우리가 조절할 수 있는 임의의 float 정보를 추가해 준다. - rand(@ptnum + chf("extra_seed"))
  • 우리의 의도 아래 스타트 프레임 SF와 엔드 프레임 EF를 만들어준다.
  • 그리고 하나의 변수를 더 만들어주는데 그것은 GAP이다. GAP은 스타트 프레임과 엔드 프레임 사이의 간극이다.
  • 스타트 프레임에도  위의 Seed Attribute를 활용해서 랜덤 한 오차를 생성해서 더해준다.
  • i@SF = SF + rand(@Seed)
  • 그리고 rand(@Seed)의 결과는 0 ~ 1 사이의 값이기 때문에 fit function을 활용해서 증폭시켜 준다.
  • floor(fit(rand(@Seed), 0, 1, chf("tA_Min"), chf("tA_Max")))
  • floor 함수는 float 결괏값을 int형으로 바꿔주기 위함이다.
  • tA_Min / tA_Max : 증폭에 대한 범위를 channel function을 활용해서 우리가 직접 지정해 줄 수 있다.
  • GAP 또한 SF와 같은 방법으로 증폭을 시켜준다.
  • 엔드 프레임은 스타트 프레임과 GAP의 합으로 인해서 만들어 낼 수 있다.
  • 높이에 대한 값 또한 Seed를 활용해서 랜덤 하게 만들어줄 수 있다.
  • height 어트리뷰트를 만들고, SF와 같은 방식으로 증폭을 시켜준 뒤(이곳에서는 굳이 int 형으로 변환할 필요는 없다.) 높이를 생성했던 노드의 상수값을 height로 바꿔준다.
  • @play와 first U / second U에 대한 생성은 위에서 해준 것을 이용한다.

 

노란 노드는 반복을 수행하기 위해 정보를 만들어준 노드들이고, 파란 노드는 반복을 진행할 노드들이다.

for each를 사용하지 않을 때의 우리가 하게 될 반복작업
짜잔

 오늘 공부 중 가장 중요한 부분은 저 위의 노란색 정보의 생성 부분이다. 우리가 통제가 가능할 수 있도록 정보를 생성해 주는 것이 매우 중요하다. 이 부분은 꼭꼭 숙지하고, 다시 해보고, 만져보고, 예제도 더 만들어보고 해서 내 것으로 만들자.


 점심시간에 점심을 먹으면서 강의를 듣는데 정말 빨리 집에 가고 싶어졌다.

 강의를 듣는 내내 작업을 하고 싶어서 머릿속이 굴러가고 이렇게 하면 되나? 저렇게 하면 될까? 하는 고민을 해보고, 손으로 끄적거려 보고 즐거운 마음으로 집에 와서 이렇게 정리를 하고 있다.

 for each는 정말 다른 어떤 튜토리얼을 보더라도 헷갈리는 부분이었으나, 뭔가 슬슬 윤곽이 잡히는 느낌이 든다. 그 무엇보다도 저런 반복적인 노가다를 하지 않게 해주는 것이 매우 고마울 따름이다.

 

 처음에 점을 가지고 만들어볼 때는, Attribute wangle을 이용할 생각은 하지도 않고, add node 두 개를 가지고 선을 만들고 carve를 적용해주고 있었다. 나중에 수업을 따라가면서 이렇게 되면 다른 지오메트리에 적용하려면 또 고민을 해야 하는 것이었겠다라고 생각을 했었다. 수업 마지막 부분에 나온 예제는 한번 머리 싸매고 만들어봐야겠다.

 

 그토록 강조했던, 정보를 생성하는 부분에 대해서는 무조건 내 것으로 만들 수 있도록 노력해야겠다.

'Houdini > Houdini1_Starter' 카테고리의 다른 글

STARTER08_Solver  (1) 2023.01.18
STARTER07_Block 반복 작업을 위하여  (0) 2023.01.16
STARTER05_Attribute 관련 Node  (0) 2023.01.12
STARTER04_Let's render  (0) 2023.01.11
STARTER03_Mantra(Material, Group)  (1) 2023.01.10