Modfy Agent Skeleton

   968   8   1
User Avatar
Member
89 posts
Joined: April 2014
Offline
I have an agent primitive that I want to modify the skeleton of. Modifying the skeleton is easy, but I am trying to find a way to update an existing agent primitive with the new modified skeleton. Is there a way to do this?

If not, and I have to create a new agent primitive through something like an Agent From Rig sop, can I copy the motion clips from an existing agent to my newly created agent?
Edited by Tyler Britton2 - Feb. 18, 2025 18:23:33
User Avatar
Member
87 posts
Joined: Jan. 2009
Offline
I think you'll need to create a new agent if you want to change the rig. You may need to re-do your skin weighting as well.

As for the motion clips, you should be able to re-target them to your new rig: https://www.youtube.com/watch?v=B4RT4OLu5E8 [www.youtube.com]

I think it depends on how drastic of a change you're making to your rig though, they may just work.
User Avatar
Staff
760 posts
Joined: Oct. 2012
Offline
In a Python SOP you can also use `hou.AgentDefinition.freeze(new_rig=...)` to make a new agent definition with a different rig (copying the clips etc to reference the new rig).
But, like the previous post suggests, if you're changing joint names you'll have limited success and would need to re-target the motion instead
User Avatar
Member
89 posts
Joined: April 2014
Offline
Thank you for the help.

The joints are all the same, so luckily, I don't need to do any retargeting.
I made a python script that will go through the input agents, and hopefully swaps the skeleton out for the one from the second input. It successfully swaps the rigs, however the skeleton doesn't seem to be swapped, it is still the one from the first input.

Any help is appreciated.

node = hou.pwd()
input_geo = node.geometry()  # This is the writable geometry in a Python SOP
reference_geo = node.inputs()[1].geometry()  # Second input (read-only)

# Get reference agent from second input
if len(reference_geo.prims()) > 0:
    reference_agent = reference_geo.prims()[0]
    reference_def = reference_agent.definition()
    reference_rig = reference_def.rig()
    reference_shape_lib = reference_def.shapeLibrary()
    print(f"Reference rig found: {reference_rig}")
    print(f"Reference definition: {reference_def}")
    print(f"Reference shape library: {reference_shape_lib}")
else:
    print("Error: No agent in reference input (second input)")
    raise hou.NodeError("No agent in reference input")

# Process each agent in the input geometry
for i, agent in enumerate(input_geo.prims()):
    print(f"\n--- Agent #{i} ---")
    
    # Get original definition and info
    original_def = agent.definition()
    print(f"Original definition: {original_def}")
    print(f"Original rig: {original_def.rig()}")
    print(f"Original clips: {len(original_def.clips())}")
    print(f"Original layers: {len(original_def.layers())}")
    print(f"Original transform groups: {len(original_def.transformGroups())}")
    
    # Create a new frozen definition with the reference rig
    new_def = original_def.freeze(new_rig=reference_rig)
    print(f"New definition created: {new_def}")
    print(f"New rig: {new_def.rig()}")
    print(f"Clips preserved: {len(new_def.clips())}")
    print(f"Layers preserved: {len(new_def.layers())}")
    print(f"Transform groups preserved: {len(new_def.transformGroups())}")
    
    # Update the agent's definition in place
    # In a Python SOP, node.geometry() is directly modifiable
    agent.setDefinition(new_def)
    
    # Verify the change
    print(f"Updated agent: {agent}")
    print(f"New agent definition: {agent.definition()}")
    print(f"New agent rig: {agent.definition().rig()}")

Reference rig found: <hou.AgentRig rig:new_agent>
Reference definition: <hou.AgentDefinition 0x0000773c34602100>
Reference shape library: None

--- Agent #0 ---
Original definition: <hou.AgentDefinition 0x000077400e9f9780>
Original rig: <hou.AgentRig rig:agent1>
Original clips: 18
Original layers: 65
Original transform groups: 7
New definition created: <hou.AgentDefinition 0x0000773c3f3aeb00>
New rig: <hou.AgentRig rig:new_agent>
Clips preserved: 18
Layers preserved: 65
Transform groups preserved: 7
Updated agent: <hou.Agent prim #0 of geometry frozen at 0x773ff5d23c00>
New agent definition: <hou.AgentDefinition 0x0000773c3f3aeb00>
New agent rig: <hou.AgentRig rig:new_agent>
User Avatar
Staff
760 posts
Joined: Oct. 2012
Offline
I'm not sure what you mean by "It successfully swaps the rigs, however the skeleton doesn't seem to be swapped" - do you mean that the agent's pose hasn't changed?
That would be expected since the rig stores only the joint hierarchy etc (anything that can be shared between instances of an agent), but each agent instance stores its own pose. hou.Agent.setDefinition() will try to maintain the agent's original pose if the new rig has some of the same joint names, but any new joints will be set to an identity local transform

On a separate note, if your input geometry might contain multiple agents that share the same agent definition, your code would create separate copies of the agent definition per agent which is less efficient. Using hou.crowds.replaceAgentDefinitions() is the simplest way to preserve instancing of the agent definitions when making changes
User Avatar
Member
89 posts
Joined: April 2014
Offline
Thanks.

Yeah, I might be misusing some of the terms or explaining them incorrectly.

Here is an example scene showing what I am trying to do. I am modifying the main "body" layer, and then trying to update the skeleton while keeping all my motion clips and everything. Please let me know if there is a better way.

Image Not Found

Attachments:
modify_agent_skeleton.hip (374.3 KB)

User Avatar
Staff
760 posts
Joined: Oct. 2012
Offline
I think if you're trying to change the skeleton like that, you would also need to update / retarget the clips to the new skeleton.

But if you're simply trying to adjust the overall scale of the agent, you could just configure `pscale` on the agent rather than editing the agent definition at all.
User Avatar
Member
89 posts
Joined: April 2014
Offline
The overall transform I did was just for simplicity, unfortunately, in production it would be more complicated the just a 'pscale' change.

Is there a procedural way I could do this all with Python? I tried with the code mentioned above which I used in the demo file, but it wasn't quite working. Maybe I was using it incorrectly.
User Avatar
Staff
760 posts
Joined: Oct. 2012
Offline
I'm not sure if doing it in Python will be very easy, since SOP tools for editing the clips will probably be much easier.
To explain further - the agent's rig only stores the topology of the skeleton (e.g. which joints exist, and the parent/child relationships), and a rest pose that's used only as a fallback (e.g. if the agent doesn't have any clips assigned). There is no information stored about bone lengths etc, so if you're trying to make changes like that to the skeleton, you actually need to instead be updating all of the agents' clips
  • Quick Links