Exporting Alembic Files from Houdini Using the Path Attribute

Jessica Beckenbach
5 min readFeb 1, 2020
Path Attribute in the ROP Alembic Output node.

When you export a model from Houdini using the ROP Alembic Output node, it comes into Maya as one mesh — no subfolders or anything. The brute force method of separating the Maya mesh and piecing it back together can be used, but that’s too time-consuming and Houdini has already created a better way of doing it — the path attribute.

When you put down a ROP Alembic Output Node, there’s a checkbox labeled “Build Hierarchy From Attribute” in the Hierarchy tab. Turn it on. This enables the ROP to read the path attribute.

Now let’s build the path attribute.

Before building the path attribute, figure out what the structure of your mesh in the Maya Outliner will be. This will make folder structure and naming conventions a lot easier (and avoids headaches later).

Here, we have a simple scene in Houdini. Here’s the folder structure we’re going to create:

Everything with the same path attribute will be turned into one mesh when you export as an alembic. Thus, it is integral that everything is named properly.

Let’s start with the cube. We have one cube mesh that will sit at the root level of the Outliner in Maya. In a primitive wrangle, put in the following code:

s@path="cubeInOutliner/cubeShape";

Since any geometry in Maya is defined by its transform container and the geometry shape itself, it needs two names. The first name is the transform container, and the second name is for the shape.

All the primitives piped into this primitive wrangle are given the string attribute of cube. Thus the format for any top level mesh is:

s@path="outlinerMeshName/shapeMeshName";

Let’s apply this to our spheres. Since we have four spheres, let’s put them in a folder. The format for subfolders is as follows:

s@path="folder1/outlinerMeshName/shapeMeshName";

There are four spheres, all of which are exact copies of each other and have the same number of primitives.

//Set the number of primitives per sphere
//My spheres have 288 prims but substitute this number
//with however many primitives you have
int prims=288
//Divide the primitive number by the number of primitives
//per sphere to get the sphere number. Then convert it
//into a string
string sphereNum=itoa(@primnum/prims);
//Build the path and concatenate @sphereNum wherever it is needed
s@path="sphereGroup/sphere"+sphereNum+"/sphere"+sphereNum;

Not too hard, is it? In fact, it can be applied to any number of sublevels:

s@path="levelOne/levelTwo/levelThree/levelFour/levelFour";

There you have it: a simple way to make some sort of hierarchy in Houdini for alembic export into Maya.

Notice how all the imported geo is prefixed with the name of the alembic? It can easily be removed with the Search and Replace names tool. Go to Modify > Search and Replace Names… In Search for, put in $. This refers to the end of the string. (Fun fact: Search and Replace works with Regex. Very deep rabbit hole. Thankfully, you don’t need to understand Regex to use Search and Replace.) In Replace with, put in a space. Maya errors out if you leave it blank. If you want to add a suffix to all your imported geo, you can put it in Replace with. Select all your imported geometry, and click “Apply.” This replaces all the names of your imported geo. Neat trick, huh?

Completed node network for the above scene

Sometimes, it’s useful to name primitives as you make them and then rename them as you duplicate them multiple times. Below are some code snippets that manipulate the path attribute in various ways.

//Set the number of primitives per sphere
//Plug in your original geo before you copied it into the
//second input of your prim wrangle
string num = itoa(@primnum / nprimitives(1) +1);
s@path="station/rightWall/topWindow/bar"+num+"/bar"+num;
//output: station/rightWall/topWindow/bar1/bar1

.

//rename the third element of an array after mirroring
//pre-mirrored geo is input #2
//before: station/rightWall/window1/bottomWindow/bar1/bar1
if(@primnum>=nprimitives(1))
{
string myArray[] = split(s@path, '/');
myArray[3] = "windowWINDOW";
@path=join(myArray,"/");
}
//after: station/rightWall/windowWINDOW/bottomWindow/bar1/bar1

.

//rename after mirroring, but only if it's door1 
//and it's the third element of the string
//pre-mirrored geo is input #2
//before: station/backWall/door1/door/door
string myArray[] = split(s@path, '/');
if(@primnum>=nprimitives(1)&&myArray[2]=="door1")
{
myArray[2] = "door2";
@path=join(myArray,"/");
}
//after: station/backWall/door2/door/door

.

//rename all "1" to "2" if it's the third element of the string
//pre-mirrored geo is input #2
//before: station/frontWall/window1/topWindow/glass/glass
if(@primnum>=nprimitives(1))
{
string myArray[] = split(s@path, '/');
myArray[2] = rstrip(myArray[2],"1")+"2";
@path=join(myArray,"/");
}
//after: station/frontWall/window2/topWindow/glass/glass

.

//if geo without the path attrib is merged with geo with the 
//path attrib, use this to rename all geo without the path attrib
if(len(s@path)<=1)
{
@path="station/roof/sideRoof/side/side";
}

And finally, here’s some handy dandy vex code for imported alembics. This code turns every part of a path into its own group, making assigning materials a breeze. So given the simple scene with four spheres and a cube above, you’d end up with six groups: “cubeInOutliner”, “sphereGroup”, “sphere0”, “sphere1”, “sphere2”, and “sphere3”.

//creates a group for each level of the path attribute
string myArray[] = split(s@path, '/');
foreach(int i; string value; myArray)
{
string splitted[] = split(value,":");
string nVal = (len(splitted)>1) ? splitted[-1] : value;
setprimgroup(0,nVal,@primnum,1,"set");
}

Update 04/29/21 because I keep on forgetting this and I need to remind myself:

//THIS DOES NOT WORK AND WILL FATAL ERROR YOUR MAYA
s@path="outlinerName";
//always do:
@path="outlinerName/shapeNodeName";

--

--

Jessica Beckenbach

Houdini / Technical Artist. SCAD Visual Effects ‘20. Lives and breathes Houdini, Nuke, Unreal, and (sometimes) Maya.