Custom ICENodes are regular ICENodes implemented as a self-installable plug-in with the C++ SDK. Like built-in ICENodes, a custom ICENode reads in data, processes it and then writes out the data. An ICENode can be used along with other custom or built-in ICENodes to create compound nodes. Input and output data comes from the other ICENodes in a graph: the data flows along eaach ICENode encapsulated in single or 2D array. The type of data encapsulation is specified when a new ICENode is registered in Softimage. For example, an ICENode can be defined with an input connection of float and an output connection of float vectors.
XSIPLUGINCALLBACK CStatus XSILoadPlugin( PluginRegistrar& in_reg )
{
in_reg.PutAuthor(L"SoftimageUser");
in_reg.PutName(L"MySimpleICENode Plugin");
enum IDs
{
ID_InPort = 0,
ID_OutPort = 1,
ID_InGroup = 100,
ID_OutGroup = 301,
ID_TMAP = 400,
ID_SMAP,
ID_CMAP,
ID_UNDEF = UINT_MAX
};
ICENodeDef nodeOpDef;
nodeOpDef = Application().GetFactory().CreateICENodeDef(L"MySimpleICENode");
// Add input port and group.
CStatus st;
st = nodeOpDef.AddPortGroup( ID_InGroup );
st.AssertSucceeded( ) ;
st = nodeOpDef.AddInputPort(
ID_InPort, // port index (defined in IDs enum)
ID_InGroup, // index of group to add port to
siICENodePortDataFloat, // data type
siICENodePortStructureSingle, // structure type
siICENodeEvaluationContextAny, // context type
L"InFloats", // port name
L"InFloats" // port scripting name
);
st.AssertSucceeded( ) ;
// Add output port and group.
st = nodeOpDef.AddPortGroup( ID_OutGroup );
st.AssertSucceeded( ) ;
st = nodeOpDef.AddOutputPort(
ID_OutPort, // port index (defined in IDs enum)
ID_OutGroup, // output group index
siICENodePortDataFloat, // data type
siICENodePortStructureSingle, // structure type
siICENodeEvaluationContextAny, // context type
L"Out2DVectors", // port name
L"Out2DVectors "// port scripting name
);
st.AssertSucceeded( ) ;
// Register a new ICENode definition
PluginItem nodeItem = in_reg.RegisterICENode( nodeOpDef );
// Set the new ICENode category
nodeItem.PutCategories(L"ICENode Category Sample");
return CStatus::OK;
}ICENode input and output ports are used for connecting to other ICENodes. Unlike the Softimage custom operators, the data doesn't come directly from other scene objects but from other ICENodes of the same graph. As we've seen in the example above, the ports are specified during the registration of a new ICENode type in the plug-in's XSILoadPlugin callback. The main computation performed by a custom ICENode is done in the Evaluate callback. The Evaluate callback uses the ICENodeContext object to get the input and output port data.
XSIPLUGINCALLBACK CStatus MySimpleICENode_Evaluate( ICENodeContext& in_ctxt )
{
// The current output port being evaluated...
ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID( );
switch( out_portID )
{
case ID_OutPort:
{
// Get the output data
CDataArrayFloat outData( in_ctxt );
// Get the input data for port ID_InPort
CDataArrayFloat inFloats( in_ctxt, ID_InPort );
// Assign the input data to the output port
CIndexSet indexSet( in_ctxt );
for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
outData[ it ] = inFloats[ it ];
}
}
break;
};
return CStatus::OK;
}The Evaluate callback is typically called in a multi-threaded context managed by Softimage, so you don't have to worry about thread locking when reading or writing the data passed to a custom ICENode. Evaluation threads are created by Softimage and assigned on a per processor basis, so there will be one thread created per processor on your machine. The data is process in several passes where each pass is assigned to a thread.
You can also tell Softimage to process your custom ICENode in a single-thread process, this is often required when you need to access all the input data in one single pass. For instance you could create a node to compute the bounding-box of a geometry which requires access to the entire set of point positions in one pass. See Single-Thread Custom ICENode for more information.
Autodesk Softimage v7.5