테드옹의 VFX
Python & Vex in Solaris 본문
Solaris 자체의 개념도 어렵지만
Solaris에서 사용하는 Python과 Vex는 정말 불친절 그 자체다.........
일단 발을 적시기 위해 SideFX에서 제공해준 Preset 코드부터 복기해보자면
node = hou.pwd()
ls = hou.LopSelectionRule()
ls.setPathPattern('%type:Light')
paths = ls.expandedPaths(node.inputs()[0]) // 내 바로 윗노드를 기준으로 Light 프리미티브의 Expanded Path의 리스트 가져옴
stage = node.editableStage()
for path in paths: //path의 데이터 타입은 pxr.Sdf.Path임, 문자열이 아니다
prim = stage.GetPrimAtPath(path) // 데이터 타입은 pxr.Usd.Prim
intensity = prim.getAttribute('inputs:intensity') // Parameter에 마우스 호버해보면 inputs:intensity라고 나옴, hou.parm()같다
intensity.Set(intensity.Get() * 0.5) // Get()함수는 hou.parm().eval()의 역할같음
여기서 알 수 있는 점
LopSelectionRule라는 방식을 통해서 Primtivie를 픽해야 Recook되지 않기 때문에 이런 방식을 택함
빈 도화지에 그림을 채워나간다는 느낌으로 클래스를 이용하면 될 듯
그리고 그 노드가 속한 stage는 node.editableStage()로 가져와야한다
ChatGPT한테 물어보면 Stage()를 쓰라고 하는데 잘못된 정보, 그런 함수는 없다
prim.getAttribute()를 사용했을 때 얻어지는 객체의 클래스는 pxr.Usd.Attribute이다
그리고 일반적인 hou.parm()처럼 하는 것이 아니라 pxr.Usd.Prim 객체를 생성해서 getAttribute()를 이용해 파라미터를 가져와야한다. 다만 해보니까 솔라리스의 prim path대신 실제 파라미터의 경로를 입력하여 hou.parm()도 가능하다
이 코드에서 알 수 있는 솔라리스 파이썬의 가장 기본적인 시작포인트는 아래와 같다.
node = hou.pwd()
stage = node.editableStage()
Component Builder 노드 안에 있는 또 다른 예시 코드이다
from pxr import Usd, Gf, UsdGeom
node = hou.pwd()
stage = node.editableStage()
spin = node.node('..').evalParm('spin') // 보다시피 보통 하는 방법인 evalParm()사용도 가능
pitch = node.node('..').evalParm('pitch')
dist = node.node('..').evalParm('dist')
rotatex = 25+pitch
rotatey = 35+spin
_prim_path = node.evalParm('asset')
if not _prim_path.startswith('/'):
_prim_path = '/' + _prim_path
prim = stage.GetPrimAtPath(node.evalParm('asset'))
bbox_cache = UsdGeom.BBoxCache(Usd.TimeCode.EarliestTime(), ['default', 'render'])
bounds = bbox_cache.ComputeLocalBound(prim).GetBox()
우연히 본 코드샘플에서 마침 내가 사용하고싶던 BBox 계산을 해주는 모습..!
자 이것들을 이용해서 실제로 활용을 해보자
[ 예시 ]
상황 01 : 외부사이트에서 USD 어셋을 다운로드 받고 Layout을 하려는데, 어셋의 각기 centroid와 사이즈가 다 달라서 어셋을 유닛단위로 스케일링 한 후 센터로 정렬시키고 싶다.
from pxr import Usd, UsdGeom
node = hou.pwd()
stage = node.editableStage()
prim = stage.GetPrimAtPath(node.inputPrims(0)[0]) // 바로 윗노드의 prim path를 리턴
bbox_cache = UsdGeom.BBoxCache(Usd.TimeCode.EarliestTime(), ['default', 'render'])
local_bbox = bbox_cache.ComputeLocalBound(prim)
bounds = local_bbox.GetBox() // min, max 바운딩박스 리턴, 하지만 자료형이 숫자가 아님
min = bounds.GetMin()
max = bounds.GetMax()
centroid = local_bbox.ComputeCentroid() // centroid 리턴
size = local_bbox.GetSize() // size 리턴
이렇게 해서 centroid와 size를 구하면 센터정렬과 유닛단위로 스케일을 수정할 수 있다.
[ 함수 ]
*인자로 들어간 문자열은 예시임
lopNode 클래스
- editableStage()
stage 클래스
- GetRootLayer()
- GetPrimAtPath()
Sdf 모듈
loputils 모듈
- fetchParameterValues(input_node, 'component:geo:variantset')
- globPrims()
ls 클래스
- setPathPattern('/ASSET_*')
- expandedPaths()
prim 클래스
- CreateAttribute('component:mtl:lastnode', Sdf.ValueTypeNames.String).Set(node.node('../OUT_mtls').path())
UsdGeom 모듈
- UsdGeom.BBoxCache(Usd.TimeCode.EarliestTime(), ['default', 'render'])
필요한 기능 사용할 때마다 업데이트 예정
'Houdini' 카테고리의 다른 글
NDC함수를 이용하여 카메라 모션블러 구하기 (0) | 2025.02.17 |
---|---|
Whitewater 탐구 (0) | 2025.02.15 |
Volume Shader Demystifying (0) | 2024.11.08 |
Fog Volume의 표면만 필터링하기 (1) | 2024.11.07 |
Solaris + Copernicus에서 표면에 디테일 주기 (1) | 2024.10.05 |