[MtoA] Scripting Standin paths


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

import maya.cmds as cmds
cmds.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 cmds
ntype = 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 ))

Object color mode

The Arnold Utility shader has an Object color mode, which assigns colors based on shape names. When we say “shapes”, we don’t mean Maya shape nodes; we mean the Arnold shapes.

C:\solidangle\mtoadeploy\2014\bin>kick -nodes | find "shape"
 box                              shape
 cone                             shape
 curves                           shape
 cylinder                         shape
 disk                             shape
 ginstance                        shape
 implicit                         shape
 nurbs                            shape
 plane                            shape
 points                           shape
 polymesh                         shape
 procedural                       shape
 sphere                           shape

All these nodes have a name parameter (for example, polymesh.name) that is a unique string identifier in the Arnold universe. So when you use the Object color mode, you get a unique color for each node.

If you’re using Softimage, note that SItoA puts the frame number into polymesh.name, so you’ll get a different color on each frame if you use the Object color mode. For example, on frame 5 a polymesh might be named “Dog_Mesh.SItoA.5000”, and on frame 6, “Dog_Mesh.SItoA.6000”.

In this render region comparison, you have frame 5 on the left, and frame 6 on the right:

In a case like this, you would use the Object ID color mode instead. SItoA automatically assigns unique IDs to the shape nodes (MtoA doesn’t).

Soccer balls and Arnold procedurals

I’m partial, but I like the Softimage soccer ball better than the Maya soccer ball.

The Softimage soccer ball is the one on the left. I took the ASS file for the soccer ball, did a few search and replace ops, and compiled my first procedural node. It’s pretty trivial, but it illustrates the basic framework. numNodes() returns the number of nodes you’re going to create; Arnold calls getNode() once for each node you create. I’m just creating one node, so I do it in getNode(), but you could also do it in init().

If you’re interested in learning more about the Arnold SDK and procedurals, you can download the SDK (docs included) at solidangle.com.

#include <ai.h>
#include <string.h>

static int init(AtNode *mynode, void **user_ptr )
  AiMsgInfo( "[soccer] -- greetings!" );
  return 1;

static int cleanup( void *d )
  return 1;

static int numNodes( void *d )
  return 1;

static AtNode *getNode( void *d, int index )

	AtByte nsides[540] = {
		4, 4, 4, 4, 4,
		// ...
		4, 4, 4, 4, 4};
	unsigned int vidxs[2160] = {
		292, 301, 12, 293, 302, 303, 304, 305, 302, 305, 306,
		169, 538, 537, 116, 168, 540, 539, 79, 151, 25, 541};

	unsigned int nidxs[2160] = {
		0, 1, 2, 3, 4, 5, 6, 7, 4, 7, 8, 9, 4, 9, 10, 11, 4, 
		// ...
		1211, 1216, 1215, 1230, 1229, 311, 322, 1231, 312};

	float vlist[1626] = {
		2.33102179f, 4.68985701f, -7.74118519f, -4.0108633f, -2.08138514f, 8.18039227f,
		1.70574367f, 2.03463793f, 9.00535202f, 2.94963598f, 0.0429565944f, 8.85224628f};

	float nlist[3696] = {
		-0.00219265698f, -0.443717808f, -0.896163881f, -0.112498537f, -0.405027777f, -0.907356858f, 
		-0.316353977f, -0.846433043f, 0.428335458f, 0.514008343f, -0.00765316607f, 0.857751012f};

	AtMatrix m;
	AiM4Identity( m );
	AtNode *n = AiNode( "polymesh" );
	AiNodeSetByte(n, "visibility", 255);
	AiNodeSetArray(n, "vlist",  AiArrayConvert(1626,  1, AI_TYPE_FLOAT, vlist));
	AiNodeSetArray(n, "nsides", AiArrayConvert(540,  1, AI_TYPE_BYTE,  nsides));
	AiNodeSetArray(n, "vidxs",  AiArrayConvert(2160,  1, AI_TYPE_UINT,  vidxs));
	AiNodeSetArray(n, "nlist",  AiArrayConvert(3696,  1, AI_TYPE_FLOAT, nlist));
	AiNodeSetArray(n, "nidxs",  AiArrayConvert(2160,  1, AI_TYPE_UINT,  vidxs));
//	AiNodeSetArray(n, "uvidxs", AiArrayConvert(384,  1, AI_TYPE_UINT,  uvidxs));
//	AiNodeSetArray(n, "uvlist", AiArrayConvert(270,  1, AI_TYPE_FLOAT, uvlist));

	AiNodeSetMatrix(n, "matrix", m );

	AiNodeSetStr(n, "name", "SISoccerBall");
	return n;

// --------------------------------------------------------------------------------
// dso hook.
// --------------------------------------------------------------------------------
  vtable->Init     = init;
  vtable->Cleanup  = cleanup;
  vtable->NumNodes = numNodes;
  vtable->GetNode  = getNode;
  strcpy_s(vtable->version, AI_VERSION);
  return 1;

[rlm] The curious case of the missing log entries

In this case, I got a debug log from a customer, but there weren’t any rlm entries in the log. As I’ve mentioned before, the Arnold log can include entries for licensing. At the Warning + Info level, you’ll get [rlm] log entries like these, if something goes wrong:

00:00:10   444MB WARNING | [rlm] could not connect to any license server


00:00:00   444MB WARNING | [rlm] wrong license version for arnold 20140305, found licenses for:
00:00:00   444MB WARNING | [rlm] arnold 20140206 (20 licenses)
00:00:00   444MB WARNING | [rlm] arnold 20140206 (20 licenses)
00:00:00   444MB WARNING | [rlm] please contact licensing@solidangle.com


00:00:03   749MB WARNING | [rlm] error checking out license for arnold (version 20140113):
00:00:03   749MB WARNING | [rlm]  * Communications error with license server (-17)
00:00:03   749MB WARNING | [rlm]  * Connection refused at server (-111)

And if you move the verbosity level up to Debug, then you’ll get some information about where Arnold is trying to get a license:

00:00:00   444MB         | [rlm] checking connection to license servers ...
00:00:05   444MB         | [rlm]  5055@LICSERVER1 ... DOWN
00:00:10   444MB         | [rlm]  5053@localhost ... DOWN

So why didn’t the customer’s log show any rlm entries? He was getting watermarks, so something must be wrong, right? Well, something was wrong: Skip License Check was enabled in the Render Settings.

No rlm log entries = Skip License Check

[Maya] The case of Xgen and [Error 6] The handle is invalid

This post is about a Maya issue on Window. It’s not an MtoA or Arnold issue.

Whenever I tried to export the selection as an XGen archive, I’d get [Error 6] The handle is invalid.

[Error 6] The handle is invalid
xgmArchiveExportBatchUI.py except block
xgmArchiveExportBatchUI.py call subprocess.Popen
mayapy "C:/Program Files/Autodesk/Maya2014/plug-ins/xgen/scripts/xgenm/xmaya/xgmArchiveExportBatch.py" 0 0 0 1.0 1.0 -destName ["'DragonArchive'"] -destDir ["'C:/Users/SOLIDANGLE/Documents/maya/projects/Support/xgen/archives/'"] -sourceFiles ["'C:/Users/SOLIDANGLE/Documents/maya/projects/Support/scenes/Dragon1.mb'"] -scriptPaths ["'C:/Program Files/Autodesk/Maya2014\\plug-ins\\xgen\\scripts'"] -loadPlugins ["'AbcExport'", "'Mayatomr'", "'xgenMR.py'"]
xgmArchiveExportBatchUI logging to C:/Users/SOLIDANGLE/Documents/maya/projects/Support/xgen/archives/DragonArchive.log

Googling [Error 6] The handle is invalid subprocess.Popen led me to the problem: I was starting Maya from the command line. When I started Maya from the Start menu, then the XGen Export Selection worked.

The reason I start Maya from the command line is because that’s the only way I can get the MtoA diagnostics in the Output Window. So something seems a little weird about how Maya handles STDOUT and STDERR 😉