목차
- 숙제 풀이
- 오늘의 숙제
- 일기
어제 숙제의 아이디어
- 우리가 가지고 있는 포인트 3개(혹은 n개)가 어떤 운동을 시작하게 될 것이다. 그리고 운동의 원인은 Solver에 있을 것이다.
- 이 때 우리는 어떠한 기준을 만들어줄 것이고, 그 기준의 안은 영역(범위)이 될 것이다.
- 우리가 가진 포인트가 운동을 하다가 이 영역 안쪽에 들어가면 condition은 red가 될 것이고, 영역 밖에 있을 때는 condition은 no가 될 것이다.
- 이때 우리가 가진 포인트가 condition이 red일 때의 시간을 redlife로써 저장해줄 것이다.(frame 단위로 저장된다.)
- 각각 포인트가 가지는 redlife가 다르게 되는데, 그 이유는 각 포인트가 움직이는 속력이 달라서 condition이 red인 영역에 머무는 시간이 각각 다르기 때문이다.
우선 포인트 하나로 작업을 해보자.
- Solver를 잘 만들어준다면, 점이 늘어나는 것은 문제가 되지 않는다.
1번 목표.
- 포인트의 위치가 x축으로 2일때 포인트가 레드로 바뀌었다가, 5을 넘어서면서 레드가 아니게 되는 것을 볼 수 있다.
add로 점을 만들고, solver를 만들자.(시작 프레임은 11)
처음 세팅을 만드는 순간에는 파라미터를 만들고, 포인트 함수를 쓰는 것들보다, 작동 자체를 실험하는 것이 중요하다.
처음부터 완벽한 시스템을 만들려고 작정하고 달려들지 않아도 좋다는 말이다.
우선, 우리가 원하는 수행을 solver가 이행할 수 있도록 구조를 만들자. 러프하게 만들어주고, 그 뒤에 정리하는 시간을 가지자.
가장 먼저 실험해 보는 것은, 등속도로 움직이는 것을 구현해보자.
솔버 안에 Attribute wrangle을 만들고, 그 아래 OUTPUT 노드를 달아주자.
@P = @P + {0.1, 0, 0};
solver를 나와서 reset simulation을 해준 뒤, 플레이해보면 등속운동을 하는 점을 확인할 수 있다.(기대한 대로 작동하고 있다.)
- solver에게 기대하는 것이 있다면, 조건에 맞게 결과를 도출해주는 것이다. 그렇다면, solver 안에는 견고한 시스템이 있고, solver 밖에서 값을 조정해주는것이 좋지 않을까?
포지션에 더해지게 될 vector 정보가 이미 Prev_Frame에 attribute 정보로 존재했다면 어땠을까? 예를 들어 @vel 이라는 vector 어트리뷰트가 있는데, 그 값이 {0.1,0,0}이라면, Attribute wrangle은
@P = @P + {0.1,0.0}; → @P = @P + @vel;
이렇게 쓸 수 있을 것이다.
그렇다면, @vel은 어디에서 정의를 내려주면 될까?
이 내용은 solver에 들어가기 전에 add와 solver 사이에서 미리 정의내려주면 된다.
add와 solver 사이에 attribute wrangle을 추가해주자.
v@vel = {0.1,0,0};
권장사항) solver 안에서 attribute wrangle을 사용할 때, 어떠한 타입의 attribute를 우리가 타입을 알고 있다 하더라도, wrangle 상단에 attribute를 선언해주고 작업하자.
- ex) @P = @P + @vel; 이 VEX에서 우리는 이미 @vel 이 vector 정보라는것을 알고 있다. 그럼에도, wrangle 상단에 v@vel; 이라고 선언을 해줘서 '나 vector 어트리뷰트 vel 사용할꺼야.'라고 해주자. 분명 지오메트리 스프레드시트 상에서는 분명히 vector이고, float이고, integer인데, type casting이 제대로 이뤄지지 않아서 오류를 발생할 수 있다. 원하는 정보가 제대로 나오지 않을 수 있다는 말이다. 그렇기 때문에 이용하기 전에 미리 type casting을 한번 해주도록 하자. 꼭 하자. 이것이 훨씬 좋은 습관이 될 것이라 선생님은 믿는다고 하셨다.(완전 맞는 말이다)
선생님은 여기에서 solver 밖에 정의했던 v@vel 을 channel vector로 정의해서 우리가 vector 정보를 임의로 넣어줄 수 있도록 하였다.
v@vel = chv("vel");
다른 조건을 달아보자.
점의 개수가 좀 더 많다면?
그 많은 점들의 vel이 모두 다르다면(모든 점들의 속도가 다 다르다면?)
새로운 wrangle 노드를 만들어주자.
vel 이라는 이름의 vector 어트리뷰트를 만들어줄 것이고, set function을 활용해서 정의내려줄 것이다.
v@vel = set( ...., 0, 0);
우리가 움직이게 하고 싶은 것은 x의 값이다. 이것은 어떤 임의의 변수로 적어주고, 나머지는 0으로 적어주기로 하였다.
(현재 우리가 원하는 움직임은 x축 방향으로의 움직임 하나이기 때문에)
이제 x에 들어갈 변수를 만들어주자.
float A라는 변수를 만들어주고, 이 값은 random한 값이었으면 좋겠다.
float A = rand(@ptnum);
각각의 포인트 번호가 시드가 되어 각기 다른 A값을 가지도록 하였다.
rand function으로 나오는 결과는 0~1 사이의 값이고, 이 값은 fit function으로 값의 영역을 바꾸기 매우 좋다. 바꿔주자.
A = fit(A, 0, 1, chf("vela"), chf("velb");
이것으로 우리가 정의내려준 @vel이라는 정보가 solver에서 활용되는 것을 확인할 수 있다.
이제 범위 영역에 따른 condition을 만들어주자.
이제는 solver가 스스로 판단해야한다. 주어진 Prev_Frame의 x값에 따라서 이 점의 condition이 red일지, no일지를 구분해줘야한다. 구분에 성공을 한다면, solver 밖에서 색을 줄 수 있을 것이다.
attribute wrangle을 만들자(solver 안쪽 이동과 관련된 attribute wrangle 아래)
어떤 판별을 할것이냐면, 우리가 가지고 있는 @P.x가 3보다 크다면 condition이 "red"였으면 좋겠고, 그렇지 않다면 "no"였으면 좋겠다.
조건문을 작성해주자.
if(@P.x > 3){
s@condition = "red";
}else{
s@condition = "no";
}
색에 대한 변경은 Solver 아래에 달아주면 될 것이다.
if(s@condition == "red"){
@Cd = set(1, 0, 0);
}else{
@Cd = set(1,1,1);
}
조건문을 달리 한다면, 우리는 영역을 벗어나는 것에 대해서도 통제할 수 있다.
if(@P.x > 1 && @P.x < 4){
s@condition = "red";
}else{
s@condition = "no";
}
영역 범위에 대한 내용은 나중에 사용자가 입력한 내용을 받을 수 있도록 수정하자.
지금은 영역 안에 머물러 있는 시간을 측정해서 남기는 작업을 진행할 것이다. 사실 어렵지 않은 내용이지만, 오늘의 핵심이다. 영역에 따른 색 표현보다 굉징히 Solver스러운 작업이다. 영역에 따라 색이 바뀌는건, 굳이 solver가 아니어도 구현이 가능할법 하지만, 체류시간을 측정한다는 것은 solver스러운게 맞다.
우리가 가진 조건을 활용해서 말로 한번 표현해보자. 이것이 말로 표현이 된다면, 분명 직접 해낼 수 있을 것이다.
condition이 red라면, redlife의 값이 이전 프레임보다 1만큼 더 커지면 된다.
이것을 조건문으로 표현한다면 아래와 같을 것이다.
if(s@condition == "red"){
f@redlife = @redlife + 1;
}
이 조건문은 condition을 판별하는 노드 아래 달아주면 된다.
이 컨셉은 낮설 수 있지만, solver 안에서 만든 redlife라는 값이 지속적으로 변화를 일으키고 있다 라는 점. 이 부분이 굉장히 중요하다. 이 부분은 나중에 가속도를 표현할 때도 알아야 될 개념이 될 것이고 중력을 표현할 때도 알아야 할 뉘앙스가 될 부분이다.
이제 남은 것은 우리가 작업한 내용을 조금 더 사용화 해줄 필요가 있다.
- move에 대한 부분은 딱히 바꿀 것이 없다. 원본의 첫번째 input으로 들어오는 attribute vel을 활용하고 있기 때문에 로 들어오기 때문이다.
- condition에서는 임의 범위의 시작값과 끝값만 밖에서 조절해줄 수 있으면 될 것 같다.
- 우리가 움직이길 바라는 포인트들은 solver의 0번 input으로 넣어줄 것이고, 영역의 최솟값, 최댓값은 1번 input을 활용해서 넣어줄 것이다. 그렇다면, 그 정보를 가지고 들어가줄 어떤 무언가가 필요하다.
- add 노드를 활용해서 점을 하나 생성하자. 이 점은 위치정보가 필요하지 않고, attribute wrangle을 달아줘서 조건의 최댓값, 최솟값을 정의내린 뒤, 1번 input에 연결해서 solver안의 condition 노드에 정보를 넘겨주자.
- 다시 한번 말하지만, 이 점의 위치정보는 중요하지 않다. 이 점이 가지고 있는 attribute가 중요하다.
- condition 노드에서 point 함수를 활용해서 넘어온 정보를 불러오자.
고난주간 1일차에서 꼭 알아야 하는 내용은, solver가 작동함에 따라 그리고 세팅을 어떻게 잡느냐에 따라 정보가 누적된다는 뉘앙스이다. 포지션에 벨로시티와 관련된 정보가 붙어서 이동하는 것은 눈에 보이기 때문에 이해하기가 한결 쉽다. 하지만 의외로 다른 정보의 값이 누적된다는 부분이 잘 와닿지 않을 수도 있다. 이 부분은 꼭 연습해두고 기억해두자.
오늘의 숙제
각 방향으로 움직이는 선을 만들어보자!
처음 시작 지점은 각각 다르다.
꺾이는 시점에 모든 점들은 랜덤한 방향으로 90도를 회전한다.(안꺾일수도 있다)
힌트
일단 하나의 점이 움직이는 것을 구상한다.
모든 점은 다른 시드를 가져야 한다.(그래야 서로 다른 랜덤한 움직임을 얻을 수 있다.)
인터벌이 있고, 인터벌에 의해서 꺾이는 타이밍이 정해진다.
진행방향에 대해서 분석이 필요하다.
일단 solver에 점이 들어가기 전에 초기 속도를 정해주는 attribute wrangle을 달아주었다.
저기에서는 channel float을 활용해서 초기 속도를 받아준 다음, vector @vel을 생성해줬다. 이 때, 약간의 초기 랜덤성을 부여해서 각 점에 대해 +/- x, +/- y 방향을 설정해주었다.
솔버 내부에서는 일단 솔버가 시작되면 카운트를 시작하는 wrangle을 만들었다. 나중에 인터벌 수치를 받았을 때, 카운트 넘버와 %(mod) 연산을 해서 나머지가 0이 된다면 방향을 전환해주기 위해서 만든 어트리뷰트였다.
점의 이동은 어제부터 오늘 선생님 강의까지 이어졌던 @vel을 이용하여 @P의 정보를 갱신해주는 것으로 대신하였다.
인터벌에 대한 데이터는 어제 숙제처럼 밖에서 사용자가 channel integer function을 이용해서 입력해준 값을 point function을 사용해서 받아줬다.
방향전환에 대한 wrangle은 위에서 설명했던 것처럼, 지속적으로 올라가고 있는 카운트 숫자를 interval 값과 mod 연산을 진행해서 조건문에 mod 연산이 0과 같다면 방향전환을 수행할 것을 적어주었다.
이 때, 선생님이 보여주신 예시를 잘 보면, 인터벌 타이밍에 방향전환을 하는 포인트가 있는가 하면, 그냥 가던 길을 계속 가는(방향전환이 없는) 포인트가 있는것을 확인하였다. 그래서 인터벌타이밍이 되면, 각 포인트의 x 좌표와 포인트 넘버, 그리고 그 때의 프레임 번호를 활용해서 rand 함수의 시드로 사용해준 뒤, 이 값을 증폭시키고 대략 세 부분으로 분류, 하나는 오른쪽, 하나는 왼쪽, 그리고 나머지는 직진을 할 수 있도록 구성해보았다.
라인으로 만드는 방법을 몰라서 점6개가 트레일 만들어서 이동하는것으로 대체해보았다 ㅠ
어제의 Solver 문제를 고민해봐서 그런 것일까, 아니면 오늘 선생님의 명쾌하고 깔끔한 노드정리들을 보면서 뭔가 배운 것이 있어서일까. 오늘의 숙제는 어찌저찌 고민하던 부분에 대해 구상은 얼추 되었다는 느낌이 들었다. (물론 코드는 매우 더럽... 더럽...)
노드 정리가 필요하다. 이니셜한 정보에 대해, 그리고 사용자 친화적으로 좀 더 바꿀 수 있는 부분에 대해서는 solver 밖으로 빼내주는 작업이 필요해보인다. 점점 재밌고 흥미로워진다.
'Houdini > Houdini1_Starter' 카테고리의 다른 글
STARTER09_고난주간 3일차_Bounce with Solver (0) | 2023.01.21 |
---|---|
STARTER09_고난주간 2일차 (1) | 2023.01.19 |
STARTER08_Solver (1) | 2023.01.18 |
STARTER07_Block 반복 작업을 위하여 (0) | 2023.01.16 |
STARTER06_ INITIAL VALUES(FOR EACH 노드 들어가기 전에) (0) | 2023.01.13 |