カスタム ICENodes は、デフォルトではマルチスレッドで処理されます。しかし、場合によっては、1 つのシングル スレッドでノードを処理する方法が必要になることもあります。 シングル スレッド処理では、マルチ スレッドのバッチ処理とは対照的に、入力データ セット全体に同時にアクセスできます。 シングル スレッド モードは、average、min、max などの単純な数学関数を実装する場合に便利です。 バウンディング ボックス ジェネレータやパーティクル衝突検出機能など、さらに高度なノードを実装するためにもこのモードを使用できます。 バウンディング ボックス ジェネレータはマルチスレッドでも実装できますが、マルチスレッド処理が終了した後で、収集された他の値の中から最小値と最大値を見つけるためにユーザが追加の操作を実行しなければなりません。
シングルスレッド処理を有効にするための最初の手順では、スレッド モデルを siICENodeSingleThreadingModel に設定します。この手順は、ICENodeDef::PutThreadingModel でのノード登録時に実行する必要があります。入力ポートと出力ポートは、以下のルールに従って定義する必要があります。
すべての入力ポートは Singleton コンテキス(siICENodeContextSingleton)で設定する必要があります。Singleton コンテキストで設定しない場合、すべての入力ポートのコンテキストをそのコンテキスト タイプによって制限する必要があります。
最初のルールに従わない場合、登録時にエラーが記録され、ICENode の登録が中止されます。
次の例では、シングルスレッド モデルを使用してジオメトリ頂点からバウンディング ボックスを生成する方法を示しています。
XSIPLUGINCALLBACK CStatus XSILoadPlugin( PluginRegistrar& in_reg ) { in_reg.PutAuthor(L"Softimage"); in_reg.PutName(L"BBoxGenerator Plugin"); in_reg.PutVersion(1,0); ICENodeDef nodeOpDef; nodeOpDef = Application().GetFactory().CreateICENodeDef(L"BBoxGenerator"); // Set the threading model to single-thread CStatus st; st = nodeOpDef.PutThreadingModel(XSI::siICENodeSingleThreading); st.AssertSucceeded( ) ; // Add input ports and groups. st = nodeOpDef.AddPortGroup(ID_G_100); st.AssertSucceeded( ) ; st = nodeOpDef.AddInputPort( ID_IN_vector3, // port index ID_G_100, // group index siICENodeDataVector3, // data type siICENodePortStructureSingle, // structure type siICENodeEvaluationContextAny, // context type L"vector3", // port name L"vector3", // port scripting name MATH::CVector3f(1.0,1.0,1.0)// default value ); st.AssertSucceeded( ) ; // Add output ports. st = nodeOpDef.AddOutputPort( ID_OUT_minPos, // port index siICENodeDataVector3, // data type siICENodePortStructureSingle, // structure type siICENodeContextSingleton, // context type L"minPos", // port name L"minPos"// port scripting name ); st.AssertSucceeded( ) ; st = nodeOpDef.AddOutputPort( ID_OUT_maxPos, // port index siICENodeDataVector3, // data type siICENodePortStructureSingle, // structure type siICENodeContextSingleton, // context type L"maxPos", // port name L"maxPos"// port scripting name ); st.AssertSucceeded( ) ; PluginItem nodeItem = in_reg.RegisterICENode(nodeOpDef); nodeItem.PutCategories(L"Custom ICENode"); return CStatus::OK; } XSIPLUGINCALLBACK CStatus BBoxGenerator_Evaluate( ICENodeContext& in_ctxt ) { ULONG nPortID = in_ctxt.GetEvaluatedOutputPortID(); switch ( nPortID ) { case ID_OUT_minPos: case ID_OUT_maxPos: { Application xsi; CDataArrayVector3f posArray( in_ctxt, ID_IN_vector3 ); CDataArrayVector3f outData( in_ctxt ); CVector3f v3fMin(FLT_MAX,FLT_MAX,FLT_MAX); CVector3f v3fMax(-FLT_MAX,-FLT_MAX,-FLT_MAX); CIndexSet indexSet( in_ctxt ); for ( CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next() ) { CVector3f& v3f = posArray[ it ]; if ( v3fMin.GetX() > v3f.GetX() && v3fMin.GetY() > v3f.GetY() && v3fMin.GetZ() > v3f.GetZ() ) { v3fMin = v3f; } else if ( v3fMax.GetX() < v3f.GetX() && v3fMax.GetY() < v3f.GetY() && v3fMax.GetZ() < v3f.GetZ() ) { v3fMax = v3f; } } if ( ID_OUT_minPos == nPortID ) { xsi.LogMessage( L"BBox Min: " + CString( v3fMin ) ); outData[ 0 ] = v3fMin; } else { xsi.LogMessage( L"BBox Max: " + CString( v3fMax ) ); outData[ 0 ] = v3fMax; } } break; }; return CStatus::OK; }