エレメント ジェネレータ ノードは、標準カスタム 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;
}