Changing ASS files with the Arnold Python API


If you want to change something in existing ASS files, don’t write an ad-hoc script or your own parser for the ASS file. Use the Arnold API. The Arnold API includes a set of Python bindings, so you can fairly quickly whip up a script to do whatever it is you need to do 🙂

For example, we recently discovered (and fixed) an issue where exported ASS files were missing procedural nodes. SItoA exports hair data in chunks (one chunk for every 200K hairs), but the exported ASS had just one procedural for the first chunk (chunk 0), but there should be one procedural for each chunk.

Here’s what the procedural for chunk 0 on frame 5 looks like. The missing procedurals would be for bin files like Hair.chunk.1.5.bin, Hair.chunk.2.5.bin, and so on.

procedural
{
 name Hair.SItoA.5000
 dso "sitoa_curves_proc.dll"
 data "//Projects/Support/Arnold_Scenes/Hair.chunk.0.5.bin"
 load_at_init on
}

So, for my first dive into the Arnold API, I put together a basic little script to add the missing procedurals. To do this, I had to learn how to:

  • Read and write ASS files
  • Iterate over nodes and find a specific type of node
  • Get parameter values from a node
  • Create new nodes
from arnold import *
import glob


ass_file = "Hair_Archive.ass"

AiBegin()
AiMsgSetConsoleFlags(AI_LOG_ALL)
AiASSLoad(ass_file, AI_NODE_ALL)

# Iterate over all shape nodes, which includes procedural nodes
iter = AiUniverseGetNodeIterator(AI_NODE_SHAPE);
while not AiNodeIteratorFinished(iter):
	node = AiNodeIteratorGetNext(iter)
	#print AiNodeGetName( node )

	# Is the node a procedural?	
	if AiNodeIs( node, "procedural" ):
	
		data = AiNodeGetStr( node, "data" )
		name = AiNodeGetStr( node, "name" )
	
		# Find all other chunk.<chunk-number>.<frame>.bin files
		chunks = glob.glob( data.replace( 'chunk.0', 'chunk.*' ) )

		# Add procedural nodes for chunks 1,2,3...
		for i in range(1,len(chunks)):
			n = AiNode("procedural");
			AiNodeSetStr(n, "name", "%s.%s" % (name, i) )
			AiNodeSetStr(n, "dso", "sitoa_curves_proc.dll")
			AiNodeSetStr(n, "data", data.replace( 'chunk.0', 'chunk.%s' % i ) )
			AiNodeSetBool(n, "load_at_init", True)

AiNodeIteratorDestroy(iter)


AiASSWrite(ass_file, AI_NODE_ALL, False)
AiEnd()

7 thoughts on “Changing ASS files with the Arnold Python API

  1. this method is correct?

    def getOutputFileName(ass_file):
    filename = None
    AiBegin()
    AiMsgSetConsoleFlags(AI_LOG_ALL)
    AiASSLoad(ass_file, AI_NODE_DRIVER)
    iter = AiUniverseGetNodeIterator(AI_NODE_DRIVER)
    while not AiNodeIteratorFinished(iter):
    node = AiNodeIteratorGetNext(iter)
    filename = AiNodeGetStr( node, “filename” )
    break
    AiNodeIteratorDestroy(iter)
    AiEnd()

    return filename

  2. There is an error when I use with your method to change .ass file which export in maya.
    It cannot find the “MayaFile” node and “MayaShadingEngine” node, it shows :
    node “MayaShadingEngine” is not installed,
    node “MayaFile” is not installed.
    and the new .ass file doesn’t have the node “MayaFile” and node “MayaShadingEngine” and node “standard”.
    I need your help!!! thanks very much

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s