Rigging assets for USD animation layers in Solaris

   2991   10   4
User Avatar
Member
6 posts
Joined: July 2017
Offline
TL;DR

Inside a SOP Modify LOP with your USD static asset model feeding in, Capture and rig USD prims directly with a capture+control HDA asset, or; put down a fully rigged HDA including geo of your asset, animate it, and transfer the transforms over to the incoming USD prims?

Post:

To artists familiar with rigging assets for the creation of an animation layer in Solaris.

I'm exploring different ways to rig a model (vehicle, for example) for the purpose of creating animation layers "on top" of a geometry layer of the model in Solaris. Demo scene attached.

Please can you give your thoughts on the two methods, or propose others. Suggest workarounds/solutions for any of the "issues" described below, or generally discuss your preferences for this type of workflow.

In the demo, I've refrained from using actual asset HDAs, and just left what would normally be an HDA for a model or a capture/control rig as SOP nodes. I also haven't implemented the actual layers in Solaris, because the question is about the chosen workflow for getting there, i.e, what bits of the process to do where.

So just assume that in production you'd have an HDA of a finished model, or possibly SOP geometry that is authored directly into a finished USD model asset, where the USD asset is in place of an HDA.

Here are two methods that take you from a static USD geometry asset in LOPS, to a geometry asset with an animation layer for a shot. For each method you would:

  • Make a model HDA asset (or just SOPS geo to USD if only using a USD model asset)
  • Make a capture and control rig HDA asset
  • Use the model asset to author a USD asset in Solaris

1. Green Example - Rig and animate USD prims directly in a SOP Modify LOP. With the USD asset ready to go, pass it into your capture and control rig HDA in a SOP Modify LOP to capture and animate the USD prims or unpacked meshes. Pass the animated prims back to Solaris with a layer break giving you the animation layer data separation. Note: Working directly on packed USD prims like this can be great for simple mechanical models. Lacks flexibility for more complicated stuff.

2. Red Example - Animate a rigged HDA and transfer motion to USD prims in a SOP Modify LOP. Author your static USD model asset from the (rigged?) HDA asset. Again pass your USD asset into a SOP Modify LOP, but instead of feeding it to an HDA that captures it and rigs, you put down your fully rigged HDA for the asset (geometry, capture & control all included) and then do your animation on that. Lastly, transfer the animation transforms and deforms over to the incoming USD prims, unpacking as necessary, being very careful of prim number ordering and all that. Back to LOPS and a new animation layer goes out to disk.


I've tried to demonstrate these two concepts with a very simple sub model, built with a simple SOPS example rig and usd asset in a "setup" area, with the two animation examples to the right in two different coloured network boxes. Inside each SOP Modify LOP is the attempt at showing the two ideas above.

Issues Encountered

Packed prim centroids

I had some issues working with packed prims in the rigs getting the centroids in the right places for axis of rotations. As an aside, perhaps you could also suggest some ways to get better control over preserving the transforms and pivot locations of rigged parts. Or transferring that back to a part after rigging it with an attribute. I tried using get & set packedtransform VEX functions to sort it out in the red Sop Modify > in the red wrangle.

@name

The @nameprim attribute is used during the capture process to match geometry (packed prims in this case) to the skeleton hierarchy @name point attribute.

The @nameattribute is also used to help arrange the hierarchy of components when authoring the same geometry to USD, but I often find I need a different hierarchy for animation than I do for USD scene graph.

I tried using another attribute nameon the capturepackedgeo SOP for rigging capture, e.g. @rig_name, but the subsequent bonedeform SOP warned @name was missing and didn't work.

Check inside the "create_SOP_asset_capture_rig" SOPnet. I've stumbled around this on the pale yellow network box by renaming according to the desired skeleton hierarchy. But it will cause problems later, because now the name attributes don't match the parts. Could be as simple as transferring the original names back after capture? Will the capture still function though...

Transferring motion from rigged HDA to non-rigged USD

Using the getpackedtransform& setpackedtransformVEX functions in the red wrangle in the red Sop Modify. It will cause problems if the prim numbers are different between the rigged HDA and the USD prims. As described in the @nameissue above, the prim structure for a rig and for a USD asset won't likely be the same.

You might want the majority of your packed prims on one root vehicle skeleton join for animation, yet for USD authoring, you want all those (g)prims available separately for a better hierarchy.

I guess you could keep them all separate in the rig too, with extra joints to capture them, but that is extra work. What am I missing?

Attachments:
example-rigging-for-usd-assets.hipnc (1009.2 KB)

User Avatar
Member
697 posts
Joined: Aug. 2013
Offline
Hi.

I have been thinking about this as well. In my head I have been thinking about doing all the rigging and animation in obj SOPs.

And then layering two assets in. The top one the model, the bottom one the USD skel with anim on it.

In terms of the nodes the top one would be a assetReference and the bottom one would be a sopCharacterImport/sopCrowdImport.

I have not got too much further than that though :-)

Best

Mark
User Avatar
Member
7 posts
Joined: Sept. 2021
Offline
I did lecture on that:
https://youtu.be/blpCOCTKBHo [youtu.be]

When you rig mechanical assets:EX

1. You can load USD geometries inside SOP and transform them by your rig. Just don't unpack them.
2. You can use transform pieces, or kinefx packed capture. As long as primintrinsics get modified it would work.
3. I keep these USD primitives hidden in viewport, while at the same time RIG is showing unpacked proxies (Houdini regular viewport is just slow when drawing USD primitives).
4. Export to USD i done with USD export SOP. You can alter the paths of your usd primitives if you want them to be in some specific folders in stage.
5. In your LDEV stage, you are just loading your assets with reference nodes, and loading your animations with sublayer nodes.

At some point I will do part II of this lecture, giving some more tips and tricks.
User Avatar
Member
53 posts
Joined: Sept. 2018
Offline
bogdana
I did lecture on that:
https://youtu.be/blpCOCTKBHo [youtu.be]

Thank you for sharing.

I also wanted to add to this endeavor with some of my progress of my own as well, I managed to both set up the pivots in SOPs as well as rig the asset with KineFX and successfully transform the pieces.

The only problem so far is that the transform matrix is inside the mesh and I wanted it to be in the parent xform, I figured one could write a custom vex to do this in Lops but I lack the sufficient knowledge, maybe someone can further this research and post an update below.

Image Not Found
Edited by terry_williams - July 22, 2023 18:09:11

Attachments:
Screenshot from 2023-07-22 17-02-20.png (76.2 KB)
Screenshot from 2023-07-22 17-01-11.png (2.7 MB)
usd_kinefx_01_baked.hiplc (1.8 MB)

User Avatar
Member
6 posts
Joined: July 2017
Offline
bogdana
I did lecture on that:
https://youtu.be/blpCOCTKBHo [youtu.be]

When you rig mechanical assets:...

Bogdana thank you for your lecture and reply; very interesting, and I would love to see the second part when it's out.

I could see from your demo of the mechanical ship asset that you had the turrets rigged up and working. It looks like at (23 m 30 s in your lecture [youtu.be], you also have a global rig control set up on your ship that would (I'm assuming) move the entire ship in world space.

I have managed to do this on its own, but not while also being able to rig the rest of the model. This is because when importing the USD geo asset to SOPS, you can choose either to not traverse (giving you access to transform the entire model, and write those transforms back to the root of the component in LOPS). (see first screenshot).

or you can traverse the gprims, for example, to give you access to the different parts on the model, like the gun turrets on your ship. In this case, you can animate those and return the transforms to the turrets. But if you transform the entire model here, those transforms get written back to each child of the component root, not to the component root itself. On my original example file, the toy submarine, this would mean that each of the parts gets transformed individually (the sail, duct, hull, planes) rather than the "/toySub" prim getting just one transform that moves everything within it. (see second screenshot).

The reason that happens is there is no "empty" primitive representing the entire asset in order to carry an "entire asset transform" back to LOPS.

Maybe you can create one in SOPS and give it the correct @pathattribute though?

At the moment, this is the main issue I cannot solve. I also understand you animated with proxy SOPS geo, and maybe that holds the key to above somehow along with some manual unpacking and transferring of the finished transforms. But I'm not sure.

Attachments:
Screenshot from 2023-07-23 12-29-48.png (19.1 KB)
Screenshot from 2023-07-23 12-29-56.png (31.6 KB)

User Avatar
Member
6 posts
Joined: July 2017
Offline
terrypxm
The only problem so far is that the transform matrix is inside the mesh and I wanted it to be in the parent xform, I figured one could write a custom vex to do this in Lops...

Terry, I tried to use your file (a similar approach to mine I think) but kept getting errors on the jointDeform (i used boneDeform) SOP. Tried to fix it - but I think mine has a bug in it where only a @name attribute will work on it. I will a report with SideFX on that I think.

To fix this problem in LOPS with VEX I guess you could use usd_localtransform [www.sidefx.com] to get one of the child transforms that moves the way you want your parent transform to move, then usd_addtransform [www.sidefx.com] to write that transform to the parent primitive (the root prim of your usd asset) and then usd_settransformreset [www.sidefx.com] to clear the transform from the child primitive (to avoid a double transform). But this is a guess. I haven't tested it. This isn't a fully procedural solution because you have to specify the primitives to act on by their primpaths, which will change from asset to asset. You can probably get them based on the incoming, but you still couldn't guarantee you'd always be 'selecting' a child prim that moved in the way you needed (with a transform you could wap onto your parent prim).

I think that the transform data probably needs to be on the correct prims in SOPS before trying to return it to LOPS. Just a feeling though :S
User Avatar
Member
31 posts
Joined: June 2010
Offline
samcarter
bogdana
I did lecture on that:
https://youtu.be/blpCOCTKBHo [youtu.be]

When you rig mechanical assets:...

Bogdana thank you for your lecture and reply; very interesting, and I would love to see the second part when it's out.

I could see from your demo of the mechanical ship asset that you had the turrets rigged up and working. It looks like at (23 m 30 s in your lecture [youtu.be], you also have a global rig control set up on your ship that would (I'm assuming) move the entire ship in world space.

I have managed to do this on its own, but not while also being able to rig the rest of the model. This is because when importing the USD geo asset to SOPS, you can choose either to not traverse (giving you access to transform the entire model, and write those transforms back to the root of the component in LOPS). (see first screenshot).

or you can traverse the gprims, for example, to give you access to the different parts on the model, like the gun turrets on your ship. In this case, you can animate those and return the transforms to the turrets. But if you transform the entire model here, those transforms get written back to each child of the component root, not to the component root itself. On my original example file, the toy submarine, this would mean that each of the parts gets transformed individually (the sail, duct, hull, planes) rather than the "/toySub" prim getting just one transform that moves everything within it. (see second screenshot).

The reason that happens is there is no "empty" primitive representing the entire asset in order to carry an "entire asset transform" back to LOPS.

Maybe you can create one in SOPS and give it the correct @pathattribute though?

At the moment, this is the main issue I cannot solve. I also understand you animated with proxy SOPS geo, and maybe that holds the key to above somehow along with some manual unpacking and transferring of the finished transforms. But I'm not sure.

I don't have scene currently in front of me, but I can give you some advices:

1. Do not unpack your USD geometries unless you want to do characters.
2. In USD import sop, you can choose exact primitive you want to import.
In example of the ship I have structure like this:
/ship
/turret1
/turret1_base
/turret1_top
/turret1_barrel
/turret2
...

I have several USD imports for several parts of the ship and also one for /ship
There wsa one tricky part, figuring out how not to do double transgorm. I'll check it tomorow and let you know, and perhaps I can send you over the scene.
User Avatar
Member
6 posts
Joined: July 2017
Offline
Htogrom
I don't have scene currently in front of me, but I can give you some advices:

1. Do not unpack your USD geometries unless you want to do characters.
2. In USD import sop, you can choose exact primitive you want to import.
In example of the ship I have structure like this:
/ship
/turret1
/turret1_base
/turret1_top
/turret1_barrel
/turret2
...

I have several USD imports for several parts of the ship and also one for /ship
There wsa one tricky part, figuring out how not to do double transgorm. I'll check it tomorow and let you know, and perhaps I can send you over the scene.

Thank you! That would be amazing.

I was trying something similar to what you described above - I created some proxy geometry inside my sopModify LOP and wrote the name and path attributes on it, hoping that it would take the xform back to LOPS and onto the "/ship". I did that thinking that there was no packed primitive representing the entire model if I wanted the child containers (/turret1, /turret2) to be the packed prims I was animating with.

It kinda worked, and I did see the double transforms. I also sometimes saw the proxy geometry (a prim circle) arrive in LOPS, which I did not want. So I must have had the wrong settings on my sopModify LOPs import tab, or on my exportUSD SOP for the write-to-disc version.

I have wondered if a rig control geo could do the job of carrying the root /ship xforms. I guess that's how your setup works?

In the meanwhile, I will keep testing out your usdImport instructions with exact prim addresses.
User Avatar
Member
6 posts
Joined: July 2017
Offline
bogdana
When you rig mechanical assets:...

Htogrom
perhaps I can send you over the scene.

I still can't quite get this to work. If you're able to give a simple example of this working I would be so grateful. I'm not able to proceed with my work until I can understand how this should be done.

If it would be easier for you, I can clean up and send my toySub geo, which has only 1 moving part (propellor). I can put it into /stage and run it through the component builder. That should give you a very simple demo USD model without any animation on it. If you're able to (I've no doubt you're extremely busy) would you be willing to add a basic rig to those prims and demo the technique you described to fix the double transforms?
User Avatar
Member
7 posts
Joined: Sept. 2021
Offline
samcarter
bogdana
When you rig mechanical assets:...

Htogrom
perhaps I can send you over the scene.

I still can't quite get this to work. If you're able to give a simple example of this working I would be so grateful. I'm not able to proceed with my work until I can understand how this should be done.

If it would be easier for you, I can clean up and send my toySub geo, which has only 1 moving part (propellor). I can put it into /stage and run it through the component builder. That should give you a very simple demo USD model without any animation on it. If you're able to (I've no doubt you're extremely busy) would you be willing to add a basic rig to those prims and demo the technique you described to fix the double transforms?

Very sorry for delay. Had couple of deadlines.
I have some pictures for you:


This is rigged asset in SOPs


This usd for the same asset with all shaders, overrides. Notice the structure in scene graph.


I load same USD file into rig. For general movement (overal asset position) you can load root of the asset. Thing is that SOP viewport is very slow in displaying packed USD, so on the left I convert it to poly, apply some temp colors. On right i just set visibility to USD primitves to be zero. Then I merge these two branches, and pack them as "body" packed primitve.


Next thing is rotor. So here I load root primitive for rotor. That is group containing all primitves related to rotor. I want to apply transformation to it. What I don't want is to apply any of overal translation to it, so you can see USD branch of that goes down and it will bypass all the rigging stuff. Key is if you load specific primitives with USD imports in the end you will be applying transformations only to them.



Then with packed capture and bone deform we rig the plane.


After that you can split out your USD primitives and for example reformat their paths, so this asset would sit in proper place in the scene. I saw this on presentations of Swiss international and RISE, really smart thing to do. So if you have vehicles, always put them in their group, following with names of actor vehicles, and then goes asset structure.


So finally you have your rig, which should have bunch of hidden usd primitives. You can export them as USD from sops via USD export rop, or just plug them to Solaris with sopimport.


In stage, when you import that, you will get whole structure, with transforms in proper places.
Note, I have mess with tailgun, think I was in a rush.


So last thing is just to sublayer that over asset.

And there it flies.

Attachments:
1 Sop_asset.PNG (982.0 KB)
02 USD asset.PNG (997.3 KB)
03 asset pieces 1.PNG (451.2 KB)
03 asset pieces 2.PNG (94.5 KB)
04 kinefx rig.PNG (759.7 KB)
05 assembly, refomrating usd paths.PNG (567.8 KB)
06 rig_final.PNG (1.1 MB)
07 import data to stage.PNG (391.9 KB)
08 sublayer over asset.PNG (974.8 KB)

User Avatar
Member
6 posts
Joined: July 2017
Offline
bogdana
Very sorry for delay. Had couple of deadlines.
I have some pictures for you:

Hi Bogdana, I just saw your reply. I completely understand the delay! Thank you very much for this, and for all the screenshots. I know that it is time-consuming. I have not worked through it all yet but I will soon after I finish a project, and will post back with my progress.

Thanks again, I really appreciate you taking the time.
  • Quick Links