David Grzesik

FortifiedOatMilk

About Me

EXPERTISE
VFX Artist
INDUSTRY
Advertising / Motion Graphics

Connect

LOCATION
Not Specified
WEBSITE

Houdini Skills

Availability

Not Specified

Recent Forum Posts

USD Crowd Agent Definition Cache Workflow Dec. 3, 2024, 6:50 p.m.

I was wondering if anyone else has attempted to cache an Agent Definition as USD? It seems ideal to leverage a USD workflow when constructing an agent that has purposes set, more easily connects materials, and in general leverages the benefits of a distributed USD structure.
This is the basic outline I have in my head:
When pulling a crowd into Solaris with the SOP Crowd Import LOP an "agent definition" primitive is created with the layers, shape library, and skeleton. It seems like another prim that holds SkelAnimations for each agent clip. Transform groups are effectively just json data and could be stuck on any primitive.
It seems feasible to cache an agent definition in this way. Now using this to interface with Houdini's crowd tools is a bit more of an issue. You would have to create a SOP that would translate all this information back to a Houdini Agent. You can do a lot with python, from the little I've dabbled with the hou.Agent and hou.AgentDefinition it seems like there would be a path for this.
Once you have your agent, you use the Houdini crowd tools as usual to sim or with motion paths or whatever. You would then need another USD interfacing layer. This would take your original USD agent definition and your crowd agents and recreate the familiar structure of instanced SkelRoots the SOP Crowd Import node creates. The difference being it uses our original definition that has a full USD structure. In this example, you could update one of the models far up the chain and have all those tweaks automatically propagate down to your entire crowd.
I feel like I'm missing something here, can anyone share their thoughts on a setup like this?
It seems like a much more unified way to organize agent files than caching an agent definition into bclip and grp and lay files. I can understand that having these clean references on disk can speed up crowd operations by loading only the file needed by the agent, but couldn't all of this just be unified as separate USD files?

How to expand variables like $HFS to actual absolute paths? July 24, 2024, 5:10 p.m.

I'm not sure if it would work, but possibly expand it through a python expression? Something like hou.expandString('$HFS') docs [www.sidefx.com].
You could also just put the whole file path in there if you have multiple variables and it will then return the whole path string for you.

Add new item to Ordered Menu via Python July 9, 2024, 6:22 p.m.

A word to the wise here, using node.type().definition().setParmTemplateGroup(ptg) will update that menu item for each instance of that hda so they will all receive this menu change as it is updating the definition's menu parm template. If that's what you want, then cool and perfect.

If you want it differing per instance of your hda, you can definitely add it as spare parms, but I don't like them living separately from the hda's parameter interface as you would have to manually add them after the node is created or add them to your node with your "OnCreated" script callback. Both leave them open to being tweaked or deleted or forgotten about.

I think a better way of doing all of this while keeping the updates unique to each individual instance of the node would be to use the node's User Data [www.sidefx.com]. For example, use this as your menu script:
hou.phm().readItems(kwargs)
And in your Scripts>Python Module, add something like this:
import json

def readItems(kwargs):
    node = kwargs['node']
    info = json.loads(kwargs['node'].userData('Menu1Data'))
    menu = []
    for i in range(len(info['labels'])):
        menu.append(info['items'][i])
        menu.append(info['labels'][i])
    return menu

def writeItem(kwargs,item,label):
    info = json.loads(kwargs['node'].userData('Menu1Data'))
    if info == '':
        info == {'labels':[],'items':[]}
    info['labels'].append(str(label))
    info['items'].append(str(item))
    kwargs['node'].setUserData('Menu1Data',json.dumps(info))
Then in your parameter interface just get a button and 2 string parms like Viklc has.
Add this callback script to the button:
hou.phm().writeItem(kwargs,kwargs['node'].parm('itemString').evalAsString(),kwargs['node'].parm('labelString').evalAsString())
And when you pres your button it should add into that menu. I didn't use this exact code, adapting it from something else I have written so I havent tested this example, but you get the gist.
I did run into the issue when writing an item the menu doesn't automatically update, you kinda have to poke it to make it refresh. I would put a little callback whenever the menu should update where I would go:
kwargs['node'].parm('menu').set(kwargs['node'].parm('menu').eval())
Just to force it to set itself to its current value. This solved my issues. A little annoying to have to spread this code into multiple locations, but it's possible and works pretty well, so Im happy.
Hope this helps!