Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags more
Archives
Today
Total
관리 메뉴

테드옹의 VFX

Python & Vex in Solaris 본문

Houdini

Python & Vex in Solaris

Tedd_Kim 2025. 1. 5. 22:15

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'])

 

 

필요한 기능 사용할 때마다 업데이트 예정