2차원에서 좌우 반전은 일반적으로 한 좌표축의 값에 -1을 곱하는 방식으로 구현할 수 있다.
예를 들어 원점을 지나가는 Y축을 기준으로 좌우 반전한다면 X 좌표에 -1을 곱하면 된다.
@P.x *= -1;
하지만 3차원에서 특정 축과 특정 포인트를 중심으로 geometry를 180도 회전시키려면 회전행렬이나 quaternion을 사용해야 한다.
이를 rotate 를 사용하는 방법과 qrotate 를 사용하는 방법 두 가지로 구현할 수 있다.
// 1. rotate() 사용하기
matrix m = ident();
float angle = radians(180);
rotate()는 geometry나 point를 직접 회전시키는 함수가 아니라 지정한 축을 기준으로 지정한 각도만큼 회전시키는 변환 정보를 행렬에 담는 함수이다.
따라서 먼저 ident()를 사용해 단위행렬을 만든다.
다음으로는 rotate()에서는 angle 단위가 radian이기 때문에 degree를 radian으로 바꿔주기 위해 radians() 함수를 사용해 준다.
vector pivot_pos = {원하는 포인트의 pos};
@P -= pivot_pos;
pivot_pos에는 회전 중심으로 사용할 위치를 지정한다.
그리고 나서 현재 point 위치인 @P에서 기준이 되는 point의 위치인 pivot_pos를 빼준다.
회전행렬은 기본적으로 원점 {0, 0, 0}을 중심으로 회전하기 때문에, 다른 위치를 중심으로 회전하려면 먼저 현재 포인트 위치를 pivot 기준의 상대 좌표로 바꿔줘야 한다.
쉽게 말하면 전체 좌표를 -pivot_pos만큼 이동시켜, 회전 중심인 pivot이 원점에 오도록 만드는 것이다.
rotate(m, angle, 기준이 될 축 vector);
@P *= m;
먼저 rotate를 통해 특정 축을 기준으로 특정 각도만큼 회전시키는 변환 정보를 행렬에 담는다.
다음에 그 회전행렬을 현재 point 위치에 곱해주면 원하는 만큼 회전이 적용된다.
@P += pivot_pos;
마지막으로 현재 point 위치는 회전을 위해 전체 좌표계를 -pivot_pos만큼 이동시킨 상태이기 때문에 다시 pivot_pos를 더해 원래 좌표계로 되돌린다.
최종 코드
matrix m = ident();
float angle = radians(180);
// find pivot point
int pivot_pt = min(primpoints(0, @primnum));
vector pivot_pos = point(0, "P", pivot_pt);
@P -= pivot_pos;
rotate(m, angle, v@edge_dir);
@P *= m;
@P += pivot_pos;
참고로 나는 특정 point도 구해야 했기 때문에 조금 더 복잡해졌는데, pivot_pos를 원하는 값으로 직접 설정해줘도 된다.
// 2. qrotate() 사용하기
float angle = radians(180);
vector axis = normalize(v@edge_dir);
vector4 q = quaternion(angle, axis);
qrotate() 는 quaternion에 저장된 회전 정보로 특정 벡터를 회전시키고, 그 결과를 반환하는 함수이다.
그렇기 때문에 quaternion()으로 회전 각도와 회전 축을 quaternion으로 미리 변환한다.
quaternion()에서도 angle 단위가 radian이기 때문에 radians() 함수를 사용해 degree를 radian으로 바꿔주었다.
vector pivot_pos = {원하는 포인트의 pos};
@P -= pivot_pos;
pivot_pos에는 회전 중심으로 사용할 위치를 지정한다.
qrotate() 는 전달받은 벡터를 rotate와 마찬가지로 기본적으로 원점{0, 0, 0}을 기준으로 회전시킨다.
그렇기 때문에 현재 point 위치를 pivot 기준의 상대 좌표로 바꿔주기 위해 현재 point 위치 @P에서 pivot_pos를 빼준다.
@P = qrotate(q, @P);
qrotate는 두 번째 인수인 벡터에 첫 번째 인수의 quaternion 회전 정보를 적용하여 결과 벡터를 반환한다.
해당 결과를 바로 현재 point 위치에 적용해 주었다.
@P += pivot_pos;
마지막으로 현재 point 위치는 앞에서 회전을 위해 전체 좌표를 -pivot_pos만큼 이동시킨 상태이기 때문에 다시 pivot_pos를 더해 원래 좌표계로 되돌린다.
최종 코드
float angle = radians(180);
vector axis = normalize(v@edge_dir);
vector4 q = quaternion(angle, axis);
// find the pivot point
int pivot_pt = min(primpoints(0, @primnum));
vector pivot_pos = point(0, "P", pivot_pt);
@P -= pivot_pos;
@P = qrotate(q, @P);
@P += pivot_pos;


각 깃털을 180도 회전한 전후 비교!
'Technical Artists > Houdini' 카테고리의 다른 글
| [Houdini] Digital Asset(HDA) 만들기 (0) | 2026.07.21 |
|---|---|
| [Houdini] VS Code에서 Houdini Python Scripting 하기 (0) | 2026.07.19 |
| [Houdini] VEXpression를 VSCode로 연결하기 (0) | 2026.07.13 |
| [Houdini] 방향 정리하기 (normal, up, axis 등) (0) | 2026.07.12 |
| [Houdini] Python scripting - hou.node() (0) | 2026.07.03 |