エレメント ジェネレータ ノードは、標準カスタム ICENode に、評価時に処理するエレメント数を定義する機能を追加したものです。現時点では、この機能はパーティクルの生成にのみ使用できます。エレメント ジェネレータ機能を有効にするには、ICENode の登録フェーズで 1 つまたは複数の出力ポート コンテキストを siICENodeContextElementGenerator に設定します。siICENodeContextElementGenerator コンテキストには他のコンテキストとの互換性がなく、指定されている唯一のコンテキストでなければなりません。
エレメント ジェネレータ ポートを定義する場合は、以下の簡単な登録ルールに従う必要があります。
すべての入力ポートは、Singleton コンテキスト(siICENodeContextSingleton)で定義する必要があります。
すべての出力ポートは、siICENodeContextSingleton または siICENodeContextElementGenerator で定義する必要があります。
これらのルールに従わない場合、登録時にエラーが記録され、ICENode の登録が中止されます。
処理対象のエレメントの数は、BeginEvaluate コールバックで MDNodeContext::PutNumberOfElementsToProcess を使用して指定する必要があります。例外的に、生成ノードで BeginEvaluate コールバックから入力ポート データへのアクセスがサポートされています。 BeginEvaluate コールバックがない場合、エラーが発生します。
以下の ICENode の例では、2D パーティクル グリッドを生成することによって、エレメント ジェネレータ機能を説明しています。
#include <xsi_application.h> #include <xsi_context.h> #include <xsi_pluginregistrar.h> #include <xsi_status.h> #include <xsi_mdnodecontext.h> #include <xsi_mdnodedef.h> #include <xsi_factory.h> #include <xsi_math.h> #include <xsi_vector3f.h> #include <xsi_indexset.h> #include <xsi_dataarray.h> // Defines port, group and map identifiers used for registering the ICENode enum IDs { ID_Size = 1, ID_G_100 = 100, ID_Vector3D = 200, ID_Elements = 201, ID_TMAP = 400, ID_SMAP, ID_CMAP, ID_UNDEF = ULONG_MAX }; using namespace XSI; XSIPLUGINCALLBACK CStatus XSILoadPlugin( PluginRegistrar& in_reg ) { in_reg.PutAuthor(L"Softimage"); in_reg.PutName(L"ICENodeGenerator Plugin"); in_reg.PutVersion(1,0); ICENodeDef nodeOpDef; nodeOpDef = Application().GetFactory().CreateICENodeDef( L"ICENodeGenerator" ); CStatus st; // Add a port to specify the size of the grid to generate st = nodeOpDef.AddPortGroup(ID_G_100); st.AssertSucceeded( ) ; st = nodeOpDef.AddInputPort( ID_Size, // port index ID_G_100, // group index siICENodePortDataLong, // data type siICENodePortStructureSingle, // structure type siICENodeContextSingleton, // context type L"Size", // port name L"Size", // port scripting name 10 // default value ); st.AssertSucceeded( ) ; // Add output ports. st = nodeOpDef.AddOutputPort( ID_Vector3D, // port index siICENodeDataVector3, // data type siICENodePortStructureSingle, // structure type siICENodeContextElementGenerator, // context type L"OutVector3D", // port name L"OutVector3D"// port scripting name ); st.AssertSucceeded( ) ; st = nodeOpDef.AddOutputPort( ID_Elements, // port index siICENodePortDataLong, // data type siICENodePortStructureSingle, // structure type siICENodeContextSingleton, // context type L"Elements", // port name L"Elements "// port scripting name ); st.AssertSucceeded( ) ; PluginItem nodeItem = in_reg.RegisterICENode(nodeOpDef); nodeItem.PutCategories(L"Custom ICENode"); return CStatus::OK; } XSIPLUGINCALLBACK CStatus ICENodeGenerator_BeginEvaluate( ICENodeContext& in_ctxt ) { CDataArrayLong inSize( in_ctxt, ID_Size ); // Total number of elements to generate ULONG nSize = inSize[ 0 ]; ULONG nElements = nSize * nSize; in_ctxt.PutNumberOfElementsToProcess( nElements ); return CStatus::OK; } XSIPLUGINCALLBACK CStatus ICENodeGenerator_Evaluate( ICENodeContext& in_ctxt ) { // The current output port being evaluated... ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID( ); switch( out_portID ) { case ID_Vector3D: { // Set the output port array with the new elements CDataArrayVector3f outData( in_ctxt ); CDataArrayLong inSize( in_ctxt, ID_Size ); ULONG nSize = inSize[ 0 ]; CIndexSet indexSet( in_ctxt ); for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next()) { ULONG nAbsIndex = it.GetAbsoluteIndex( ); ULONG x = nAbsIndex % nSize; ULONG y = nAbsIndex / nSize; MATH::CVector3f v; v.PutX( x * 1.0f - nSize/2 ); v.PutY( y * 1.0f - nSize/2 ); v.PutZ( 0.0f ); outData[ it ] = v; } } break; case ID_Elements: { // Returns the number of elements to generate CDataArrayLong outData( in_ctxt ); outData[ 0 ] = in_ctxt.GetNumberOfElementsToGenerate( ); } break; }; return CStatus::OK; }