The case of the disappearing particles


In this case, nParticles (render type = point) weren’t visible behind a refractive plane:
particles_not_visible

For the points render type, you get an Arnold points shape (with mode “disk”), so I exported an ASS file to see the parameter settings on the points node. I noticed the visibility 243 right away (the default visibility is 255, which is visible to all rays). And sure enough, in the Render Stats for the particle shape, some rays were turned off (and the check boxes were disabled too).
particles_render_stats

I used the User Options to force the visibility to 255
particles_useroptions
and the particles behind the refractive surface appeared:
particles_visible

This is a Maya thing. For most particle render types, the particles are not visible in reflections or refractions. It says so in the docs:

You can turn on reflections, refractions, and shadows when you software render Clouds, Tubes, and Blobby Surfaces

I’m not sure where the default values are set, but I did find the AEtemplate code that disables the render stats for all particle render types except the “s/w” type:

// C:\Program Files\Autodesk\Maya2015\scripts\AETemplates\AEparticleLayout.mel
		if( $value == 7 || $value == 8 || $value == 9 ) {
			// software particle type
			editorTemplate -dimControl $nodeName "visibleInReflections" false;
			editorTemplate -dimControl $nodeName "visibleInRefractions" false;
			editorTemplate -dimControl $nodeName "castsShadows"    		false;
			editorTemplate -dimControl $nodeName "receiveShadows" 		false;
			editorTemplate -dimControl $nodeName "primaryVisibility" 	false;
		} else {
			// hardware particle type
			editorTemplate -dimControl $nodeName "visibleInReflections" true;
			editorTemplate -dimControl $nodeName "visibleInRefractions" true;
			editorTemplate -dimControl $nodeName "castsShadows"			true;
			editorTemplate -dimControl $nodeName "receiveShadows" 		true;
			editorTemplate -dimControl $nodeName "primaryVisibility" 	true;
		}

So, since that AE template code just enables and disables UI controls, but doesn’t change the actual values, another way to enable Visible in Refractions (or Visible in Reflections) is to do this:

  1. Change the Particle Render Type to one of the “s/w” types, like Blobby Surface.
  2. Now the Visible in Refractions check box is enabled.
  3. Select the check box.
  4. Go back and change the Particle Render Type to points.

Now when you render, the points are visible to refraction rays, so they show up behind the glass.

[Arnold] [Python] Iterating over the shape nodes in a scene


Here’s a snippet that loops over the shape nodes in an ASS file.

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:/softimage/projects/Support/Arnold_Scenes/Default_Pass_Main.1.ass')

# Iterate over all shape nodes
iter = AiUniverseGetNodeIterator(AI_NODE_SHAPE);
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 ) )
	
AiNodeIteratorDestroy(iter)
AiEnd()

This would print something like this:

C:\solidangle\scripts>python shapes.py
[script] AiNodeGetName: root
[script]  AiNodeEntryGetName: list_aggregate
[script]  AiNodeEntryGetType: 8
[script]  AiNodeEntryGetTypeName: shape
[script] AiNodeGetName: cube.SItoA.1000
[script]  AiNodeEntryGetName: polymesh
[script]  AiNodeEntryGetType: 8
[script]  AiNodeEntryGetTypeName: shape

Note the root node of type list_aggregate. It’s shape used internally by Arnold. Just be aware that that root node is there in the universe, because even if you load an ASS file that contains just polymesh nodes, there will be a root node that you’ll have to skip over.

[MacOSX] Troubleshooting with dtruss


In a previous post, I looked at how things could go wrong in the file ~/pymel.log wasn’t accessible. On Windows, this was fairly easy to track down using Process Monitor:
pymel.log

On Mac OS X, I had to use dtruss. For example, I ran this command to trace the syscalls of the Maya Render command:

sudo dtruss -f -t open_nocancel -n Render 2> /var/tmp/mtoarender.log

When the render job failed, I checked the log file, and found this line:

11668/0x35deb: open_nocancel("/Users/stephenblair/pymel.log\0", 0x601, 0x1B6) = -1 Err#13

One important gotcha: if you repeat the render, you won’t find any mention of pymel error in the dtruss output. My guess is that at that point, the Render command ends up going through the file system cache, so dtruss doesn’t see the attempt to find pymel.log.

Here’s a quick summary of the dtruss command I showed above:

  • Use sudo to run dtruss, because it needs additional privileges.
  • -f tells dtruss to follow any child processes (like mayabatch) launched by Render
  • -t filters the trace for open_nocancel system calls
  • -n tells dtruss to trace the process named “Render”
  • 2> /var/tmp/mtoarender.log redirects the dtruss output to a file

The case of the “cannot remove alias” RuntimeError


In this case, mayabatch reported some runtime errors when loading a certain scene:

# Traceback (most recent call last):
#   File "C:\solidangle\mtoadeploy\2015\scripts\mtoa\callbacks.py", line 415, in deferredCallback
#     func(*args, **kwargs)
#   File "C:\solidangle\mtoadeploy\2015\scripts\mtoa\aovs.py", line 471, in createAliases
#     pm.aliasAttr(sg + '.ai_aov_' + name, remove=True)
#   File "C:\Program Files\Autodesk\maya2015\Python\lib\site-packages\pymel\internal\pmcmds.py", line 134, in wrappedCmd
#     res = new_cmd(*new_args, **new_kwargs)
# # RuntimeError: 'aiStandardSG.ai_aov_direct_specular' is not a unique name.  Cannot remove alias.

Now, even though I have the advantage of access to the MtoA source code, the problem remained: how do I fix the scene and stop these errors? To find a solution (and understand the problem) I had to resort to examining the Maya ASCII version of the scene.

The “fix” was to clear the AOV names on the shadingEngine node:

setAttr "aiStandardSG.aovs[0].aov_name" -type "string" ""; 
setAttr "aiStandardSG.aovs[1].aov_name" -type "string" ""; 
setAttr "aiStandardSG.aovs[2].aov_name" -type "string" ""; 

The problem is that the shadingEngine node has some named custom AOVs, but no corresponding “attribute alias” list. So the AOV name couldn’t be found in the alias list, which in the error message came out as “not a unique name”.

In the Maya ASCII version of the problem scene, I saw this:

createNode shadingEngine -n "aiStandardSG"; 
	addAttr -ci true -h true -sn "aal" -ln "attributeAliasList" -dt "attributeAlias"; 
	setAttr -s 4 ".aovs"; 
	setAttr ".aovs[0].aov_name" -type "string" "direct_diffuse";
	setAttr ".aovs[1].aov_name" -type "string" "direct_specular";
	setAttr ".aovs[2].aov_name" -type "string" "indirect_diffuse";
	setAttr ".aovs[3].aov_name" -type "string" "indirect_specular";

instead of this:

createNode shadingEngine -n "aiStandard1SG";
	addAttr -ci true -h true -sn "aal" -ln "attributeAliasList" -dt "attributeAlias";
	setAttr ".ihi" 0;
	setAttr ".ro" yes;
	setAttr -s 4 ".aovs";
	setAttr ".aovs[0].aov_name" -type "string" "direct_diffuse";
	setAttr ".aovs[1].aov_name" -type "string" "direct_specular";
	setAttr ".aovs[2].aov_name" -type "string" "indirect_diffuse";
	setAttr ".aovs[3].aov_name" -type "string" "indirect_specular";
	setAttr ".aal" -type "attributeAlias" {"ai_aov_direct_diffuse","aiCustomAOVs[0]",
			"ai_aov_direct_specular","aiCustomAOVs[1]",
			"ai_aov_indirect_diffuse","aiCustomAOVs[2]",
			"ai_aov_indirect_specular","aiCustomAOVs[3]"} ;

I don’t know how the user managed to get the scene into that state 😉

The case of the missing PyMel debug log file


In several recent cases, I had to figure out why MtoA wouldn’t load on a render farm. The root cause turned out to be the PyMel debug log: ~/pymel.log

If PyMel cannot find or open ~/pymel.log, that stops PyMel and anything that uses PyMel (like MtoA).

On a render farm, this can happen if the render manager user account doesn’t have a home folder, ~/pymel.log doesn’t expand to a valid location, or if user doesn’t have read-write permissions on pymel.log.

For example, here’s the Process Monitor log when ~ cannot be resolved:
pymel.log.2
And here’s the log when the user doesn’t have read-write permissions:
pymel.log
The location of pymel.log is specified by the pymel.conf configuration file, like this:

os.path.expanduser('~/pymel.log')

When there’s a problem with the PyMel debug log, it can be hard to tell from the MtoA errors. You may see API errors like this (but the line numbers all point to unrelated bits of source code). However, if you see these line numbers with the MtoA 1.x, it’s probably a pymel.log problem.

API error detected in plugins\mtoa\Main.cpp at line 794
: (kFailure): Unexpected Internal Failure
00:00:00   514MB ERROR   | Failed to register renderer 'arnold'

API error detected in plugins\mtoa\Main.cpp at line 716
: (kFailure): Unexpected Internal Failure
00:00:00   514MB ERROR   | Failed to register Arnold swatch renderer

API error detected in plugins\mtoa\Main.cpp at line 716
: (kFailure): Unexpected Internal Failure
00:00:00   515MB ERROR   | Failed to register Arnold swatch renderer

You might also see errors like this:

API error detected in plugins/mtoa/Main.cpp at line 794
: (kFailure): Unexpected Internal Failure
Error: line 1: IOError: file /Applications/Autodesk/maya2015/Maya.app/Contents/Frameworks/Python.framework/Versions/Current/lib/python2.7/logging/__init__.py line 916: 13
Error: line 1: Failed to register renderer 'arnold'
Error: line 1: initializePlugin function failed (mtoa)

Running multiple Arnold instances on the same computer


Arnold licenses are shared by host. That means all Arnold instances running on the same computer share the same license.

For example, you can have multiple copies of Houdini running on your computer, all doing render regions with HtoA, and you’ll be taking just a single Arnold license. Same thing with Softimage and Maya.

License sharing is defined by your license. The share=h in your license means that all processes (aka instances) running on the same host (aka computer) can share a single license.
license_file_share

Even when licenses are shared, you will still see multiple checkouts in your license usage. For example, here’s my license usage when I have an IPR going in Maya, and render regions in Softimage and Houdini:
share_license_usage
The debug log would show something similar:
share_debug_log
It might look like there are three licenses checked out, but it’s not. It’s just one license, checked out three times (aka shared three times).

If I check my license pool status, I can see that one license is in use:
share_license_pool_status

And if you have reporting enabled, you can check the report and see that all three licenses have the same share handle (which means that the license is being shared):
share_report_log