As part of the pipeline I’m currently writing for Timber, I’ve been working on an input/output system that can pass data back and forth between Maya and Houdini. The goal is to have a Maya artist send an Alembic scene to Houdini, process the scene in Houdini, then send the modified scene back to Maya. The problem is when you want the scene to be recognizable at all, and also easy to work with in Houdini.

There are several steps to making this process work, and you’re better off scripting as much as you can because it’s annoying and repetitive. Also, the method I’m using will preserve the scene hierarchy, but it will not preserve pivots or transform information (everything becomes baked to world space). Hopefully there will be a better way to manage that soon.

First off, when you import the Alembic, use an Alembic Archive geometry container. Disable “Build Hierarchy Using Subnetworks” and then build the hierarchy. Instead of packing each child transform inside subnetworks for the whole Alembic hierarhcy, you should get a flattened hierarchy inside your Alembic Archive that looks like Fig. 1.

Fig. 1. A flattened Alembic subnet. All the geometry exists inside this subnetwork, with no child subnetworks.

Fig. 1. A flattened Alembic subnet. All the geometry exists inside this subnetwork, with no child subnetworks.

The reason you want this flattened hierarchy is so that you can merge everything into another network easily. I prefer to import all my data in one place, then Object Merge it into another network to modify it in order to keep everything nice and readable. Since everything is flat, on the Object Merge node you can just merge in /obj/alembicarchive1/* and everything should appear nicely. In order to preserve the original hierarchy for export, though, we’re going to want to enable “Create Per-Primitive Path” so that a primitive attribute objname appears on every packed Alembic primitive we’re reading into the scene.

This objname parameter isn’t storing exactly what we want, though. It’s storing the path to the SOP in Houdini’s terms, not the path the object had in the original export. If you look inside the Alembic Archive you originally created and click on any of the Alembic nodes inside, you can see that there’s an objectPath parameter that is storing the original Alembic path. We just need to get this value for each primitive. Since we have objname already stored, it’s not too hard to get objectPath from each packed primitive. We just need to use a little VEX (don’t worry).

Drop down an Attribute Wrangle after your Object Merge, and try the following code:

string objname;
objname = prim(geoself(),"objname",@primnum);
// get objectPath attribute from the parent node of objname
string channame = sprintf(objname + "/objectPath");
string objpath = chs(channame);
s@abcPath = objpath;

First we fetch the Houdini object path (stored as objname) on each primitive. Next, we generate a string for the channel name that we want to query, which is objname + "/objectPath", the channel name that contains the original Alembic path of the object. We then use chs() to grab the value of that channel, and store it as a primitive string attribute called abcPath. Not too bad. If you look at the object now in the Geometry Spreadsheet, you can see that each primitive now has a string attribute pointing to the Houdini path as well as the original Alembic path of each object.

There’s another little catch here. We’re probably going to want to convert this geometry to regular Houdini geometry, since there’s not a lot we can do with packed primitives (or polygon soups, depending on what you’re trying to do). So we’ll need to append an Unpack SOP. When you unpack, though, you’ll notice your primitive attributes are gone. To transfer the primitive attribute onto the newly unpacked polygon soups, just enter abcPath into the Transfer Attributes parameter on the Unpack SOP. Now every primitive should have the correct attribute, and you can go ahead and drop down a Convert SOP to convert everything into standard Houdini geometry.

You can go ahead and smash up the geometry to your heart’s content now, as long as you maintain those primitive attributes. When you’re done and it’s time to export an Alembic, all you have to do on the Alembic ROP is select “Build Hierarchy From Attribute” and type in abcPath as your Path attribute. If you were to load the exported .ABC file back into Maya, you should see that the object names and their hierarchical relationship to each other should be unchanged (although your pivots will all be at the origin, and the transforms frozen). Now your Maya team won’t freak out when everything in your Houdini scene comes in as one giant unrecognizable object!

Categories: HoudiniMaya

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts


A Long-Winded Guide to Houdini Instancing

On the Houdini Discord server(s) I keep seeing the same kinds of questions over and over again, mostly related to instancing. The most common questions asked seem to be: “How do I randomly rotate/scale my Read more…


The joy of xyzdist() and primuv()

I’m going to try to make a nice easy introduction to my two favorite functions in Houdini VEX (besides fit01 and chramp of course): xyzdist and primuv. These functions are at the core of a Read more…


Branching circuits experiment

My good friend and motion graphics bromance, Eli Guerron, asked me to help him create a procedural system of branching circuits that would look something like a schematic drawing. I stupidly thought this would be Read more…