Scripting – Arnold Support Corner (2023)

Posted on October 8, 2021 by xsisupport

Reply


First, set things up so you can use the Arnold Python API. On Windows:

set PATH=C:\Users\blairs\AppData\Local\Programs\Python\Python39;%PATH%set PYTHONPATH=C:\solidangle\arnold\Arnold-6.2.1.1-windows\pythonrem Sometimes necessaryset PATH=C:\solidangle\arnold\Arnold-6.2.1.1-windows\bin;%PATH%

Then, run this Python script, which does the following:

  • Sets the logging verbosity
  • Loads an ASS file
  • Loops over all the shader nodes.
  • If a shader is a standard_surface, inspect the ID AOV parameters.
from arnold import *AiBegin() AiMsgSetConsoleFlags(AI_LOG_ALL) # Required if the ASS file uses any SItoA shaders#AiLoadPlugins('C:/softimage/workgroups/sitoa-3.4.0-2015/Addons/SItoA/Application/Plugins/bin/nt-x86-64') AiASSLoad('C:/Users/blairs/Documents/maya/projects/default/scenes/denoiseme.0009.ass') # Iterate over all shader nodesiter = AiUniverseGetNodeIterator(AI_NODE_SHADER);while not AiNodeIteratorFinished(iter): node = AiNodeIteratorGetNext(iter) print( "[script] AiNodeGetName: {0}".format( AiNodeGetName( node ) ) ) ne = AiNodeGetNodeEntry( node )# print( "[script] AiNodeEntryGetName: {0}".format( AiNodeEntryGetName( ne ) ) )# print( "[script] AiNodeEntryGetType: {0}".format( AiNodeEntryGetType( ne ) ) )# print( "[script] AiNodeEntryGetTypeName: {0}".format( AiNodeEntryGetTypeName( ne ) ) ) if AiNodeIs( node, "standard_surface" ): # Plain color ID AOVs are easy aov_id1 = AiNodeGetStr( node, "aov_id1" ) print( "[script] aov_id1={0}".format( aov_id1 ) ) id1 = AiNodeGetRGB( node, "id1" ) print( "[script] id1={0} {1} {2}".format( id1.r, id1.g, id1.b) ) # ID AOVs that use a linked shader take a bit more work aov_id2 = AiNodeGetStr( node, "aov_id2" ) print( "[script] aov_id2={0}".format( aov_id2 ) ) if AiNodeIsLinked( node, "id2" ): id2 = AiNodeGetLink( node, "id2" ) print( "[script] id2={0}".format( AiNodeGetName( id2 ) ) )AiNodeIteratorDestroy(iter)AiEnd()

Posted on December 9, 2015 by xsisupport

Reply

Loading MtoA isn’t enough to create the defaultArnoldRenderOptions node. The defaultArnoldRenderOptions node isn’t created until a user opens the Arnold Render Settings for the first time.

In code, you can do it like this:

from mtoa.core import createOptionscreateOptions()# Set default render optionssetAttr( "defaultArnoldRenderOptions.motion_blur_enable", 1 )

When createOptions() creates the defaultArnoldRenderOptions node, it also creates the defaultArnoldDisplayDriver, defaultArnoldDriver, defaultArnoldFilter nodes and hooks them up to the defaultArnoldRenderOptionsnode.

Scripting – Arnold Support Corner (1)

Note that for setting defaults like this, you can also user a userSetup.py file. createOptions() calls hook functions that you can implement in your userSetup.py.

Posted on May 5, 2015 by xsisupport

Reply

Scripting – Arnold Support Corner (2)
Here’s a snippet that shows how to create a simple four-polygon polymesh node with the Arnold Python API.

n = AiNode( "polymesh" )AiNodeSetStr( n, "name", "grid" )nsides = [4, 4, 5, 6]AiNodeSetArray( n, "nsides", AiArrayConvert(len(nsides), 1, AI_TYPE_UINT, (c_uint*len(nsides))(*nsides) ) )vidxs = [0, 1, 4, 3, 1, 2, 5, 4, 3, 4, 7, 6, 9, 4, 5, 11, 8, 10, 7]AiNodeSetArray( n, "vidxs", AiArrayConvert(len(vidxs), 1, AI_TYPE_UINT, (c_uint*len(vidxs))(*vidxs) ) )nidxs = [0, 1, 2, 3, 1, 4, 5, 2, 3, 2, 6, 7, 8, 2, 5, 9, 10, 11, 6]AiNodeSetArray( n, "nidxs", AiArrayConvert(len(nidxs), 1, AI_TYPE_UINT, (c_uint*len(nidxs))(*nidxs) ) )vlist = [-1, 0, -1, -1, 0, 0, -1, 0, 1, -0.197835326, 0, -0.742445886, 0, 0, 0, 0, 0, 1, 0.802164674, 0, -0.742445886, 1, 0, 0, 1, 0, 1, 0.270379633, 0, -1.21302056, 1, 0, 0.508926511, 0.496316135, 0, 1]AiNodeSetArray( n, "vlist", AiArrayConvert(len(vlist), 1, AI_TYPE_FLOAT, (c_float*len(vlist))(*vlist) ) )nlist = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]AiNodeSetArray( n, "nlist", AiArrayConvert(len(nlist), 1, AI_TYPE_FLOAT, (c_float*len(nlist))(*nlist) ) )m = AtMatrix( 1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,0, 0, 0, 1 )am = AiArrayAllocate(1, 1, AI_TYPE_MATRIX)AiArraySetMtx( am, 0, m )AiNodeSetArray( n, "matrix", am )AiNodeSetBool( n, "smoothing", True )AiNodeSetByte(n, "visibility", 255 )# Assign a shader to the polymesh nodeu = AiNode( "utility" )AiNodeSetStr( u, "name", "aiUtility1" )AiNodeSetPtr( n, "shader", u )

And here’s the resulting node in the ASS file:

polymesh{ name grid nsides 4 1 UINT4 4 5 6 vidxs 19 1 UINT 0 1 4 3 1 2 5 4 3 4 7 6 9 4 5 11 8 10 7 nidxs 19 1 UINT 0 1 2 3 1 4 5 2 3 2 6 7 8 2 5 9 10 11 6 vlist 12 1 POINT -1 0 -1 -1 0 0 -1 0 1 -0.197835326 0 -0.742445886 0 0 0 0 0 1 0.802164674 0 -0.742445886 1 0 0 1 0 1 0.270379633 0 -1.21302056 1 0 0.508926511 0.496316135 0 1 nlist 12 1 VECTOR 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 smoothing on visibility 255 matrix 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 shader "aiUtility1"}

Posted on April 29, 2015 by xsisupport

Reply

Scripting – Arnold Support Corner (3)
MtoA provides an arnoldFlushCache command (and the Arnold > Flush Caches menu uses that command). You can call it from Python like this:

import maya.cmds as cmdscmds.arnoldFlushCache( textures=True )

Posted on March 31, 2014 by xsisupport

Reply

Scripting – Arnold Support Corner (4)

To set a standin path, use the aiStandin.dso attribute:

import maya.cmds as cmdscmds.setAttr( 'ArnoldStandInShape.dso','C:/Users/SOLIDANGLE/Documents/BlueDog.ass', type='string' )print cmds.getAttr( 'ArnoldStandInShape.dso' )

Here’s one way to list some of the attributes on a standin shape node, and find out what attribute to set:

import maya.cmds as cmdsntype = cmds.nodeType( "ArnoldStandInShape" )print cmds.attributeInfo( inherited=False, t=ntype )for x in cmds.attributeInfo( inherited=False, t=ntype ): print "%s = %s" % (x, cmds.getAttr( "ArnoldStandInShape.%s" % x ))

Posted on July 23, 2013 by xsisupport

3

Starting with version 2.8, SItoA no longer supports the Softimage motion blur property. Instead, you use the Arnold Parameters property to control transformation and deformation motion blur.
Scripting – Arnold Support Corner (5)

However, you cannot add an Arnold Parameters property to a camera (at least not using the SItoA custom menus, which will tell you that a camera is “is not a valid Object to add Arnold Parameters to”). Here’s a couple of ways to work around that:

  • Create an Arnold Parameters property on a polygon mesh, and then in the Explorer, drag that property to your Camera.
  • Select your camera and run this Python snippet:
    cam = Application.Selection(0)cam.AddCustomProperty( "Arnold_Parameters" )

Posted on April 11, 2013 by xsisupport

1

A standin can load an animation sequence, such as circling_cubes.[1..25].ass.
For example, if you open an Arnold_Standin property, click Browse, and select a sequence, Softimage automatically inserts a [Frame] token into the file name:

Scripting – Arnold Support Corner (6)

By default, that [Frame] token resolved to the current frame, but you can override that and use an expression to drive the sequence.

For example, if you have a 25-frame sequence of ASS files, you may want to play the 25 frames and then stop. To do that, you could use this expression:

 MIN(Fc,25) 

If you wanted to continuously loop the 25 frame sequence, you could use an fmod (modulo) expression like this:

 cond( fmod( Fc, 25 ) == 0, 25, fmod(Fc,25) ) 

And if you wanted to show just frames 10 to 25, you could use this expression:

 cond( Fc<10 , 10 , MIN(Fc,25) ) 

If you’re not sure about these expressions, try playing with them in the Expression Editor. As you move through the timeline, watch the Current Value update in the Expression Editor.
Scripting – Arnold Support Corner (7)

Posted on April 3, 2013 by xsisupport

7

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 globass_file = "Hair_Archive.ass"AiBegin()AiMsgSetConsoleFlags(AI_LOG_ALL)AiASSLoad(ass_file, AI_NODE_ALL)# Iterate over all shape nodes, which includes procedural nodesiter = 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 fileschunks = 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()

References

Top Articles
Latest Posts
Article information

Author: Domingo Moore

Last Updated: 17/12/2023

Views: 5891

Rating: 4.2 / 5 (53 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Domingo Moore

Birthday: 1997-05-20

Address: 6485 Kohler Route, Antonioton, VT 77375-0299

Phone: +3213869077934

Job: Sales Analyst

Hobby: Kayaking, Roller skating, Cabaret, Rugby, Homebrewing, Creative writing, amateur radio

Introduction: My name is Domingo Moore, I am a attractive, gorgeous, funny, jolly, spotless, nice, fantastic person who loves writing and wants to share my knowledge and understanding with you.