マルチフェーズ プロセス モデルでは、シングル フェーズまたはマルチ フェーズのどちらでもカスタム ノードを使用して入力データを処理できます。各フェーズには処理する入力ポートを類似したコンテキストにグループ化して含めることができます。 マルチ フェーズ評価モデルの主な目的は、入力ポートが評価される方法を最適化することです。 たとえば、フェーズ 0 で 1 つのポートを引き出します。次に、それ以降のフェーズで引き出すポートは、フェーズ 0 で読み取ったデータに基づいて決定することができます。
入力コンテキスト タイプを自由に指定できます。ロード時に Softimage によって検証が実行されることはありません。 たとえば、トポロジが異なるまたはデータ セットが異なる(法線とポイントなど)2 つのオブジェクトのポイントへ、同じオブジェクトから接続するように選択できます。
引き出すポートは同じコンテキスト タイプを共有する必要があります。共有しない場合はエラーが発生します。 ただし、Singleton コンテキストとフェーズ コンテキストを混在させることはできます。
最終フェーズで引き出すポートは出力ポートのコンテキスト タイプと同一である必要があります。同一でない場合はエラーが発生します。
SubmitEvaluationPhaseInfo コールバックを渡す必要があります。
以下のワークフローは一般的なマルチフェーズのカスタムICENodeの実装方法を示しています(詳細な例についてはを参照)。
BeginEvaluate コールバックおよび EndEvaluate コールバックもオプションで、最終評価フェーズ中にのみ呼び出されます。
ICE ノードの定義を使用して、スレッド モデルをマルチフェーズに設定します(siICENodeMultiEvaluationPhase)。
CStatus RegisterMultiPhaseSample( PluginRegistrar& in_reg )
{
ICENodeDef nodeDef;
nodeDef = Application().GetFactory().CreateICENodeDef(L"MultiPhaseSample",L"Multi Phase Sample");
CStatus st;
st = nodeDef.PutThreadingModel(XSI::siICENodeMultiEvaluationPhase);
st.AssertSucceeded( ) ;
// Add input ports and groups.
st = nodeDef.AddPortGroup(ID_G_100);
st.AssertSucceeded( ) ;
st = nodeDef.AddPortGroup(ID_G_102);
st.AssertSucceeded( ) ;
st = nodeDef.AddPortGroup(ID_G_103);
st.AssertSucceeded( ) ;
st = nodeDef.AddPortGroup(ID_G_114);
st.AssertSucceeded( ) ;
st = nodeDef.AddInputPort(ID_IN_condition,ID_G_100,siICENodeDataBool,siICENodeStructureSingle,siICENodeContextSingleton,L"condition",L"condition",true);
st.AssertSucceeded( ) ;
st = nodeDef.AddInputPort(ID_IN_true,ID_G_102,siICENodeDataFloat,siICENodeStructureSingle,siICENodeContextSingleton,L"true",L"true",1.0f);
st.AssertSucceeded( ) ;
st = nodeDef.AddInputPort(ID_IN_false,ID_G_103,siICENodeDataFloat,siICENodeStructureSingle,siICENodeContextSingleton,L"false",L"false",1.0f);
st.AssertSucceeded( ) ;
st =nodeDef.AddInputPort(ID_IN_points,ID_G_114,siICENodeDataVector3,siICENodeStructureSingle,siICENodeContextComponent0D|siICENodeContextSingleton,L"points",L"points",MATH::CVector3f(1.0,1.0,1.0));
st.AssertSucceeded( ) ;
// Add output ports.
st = nodeDef.AddOutputPort(ID_OUT_results,siICENodeDataVector3,siICENodeStructureSingle,siICENodeContextComponent0D|siICENodeContextSingleton,L"results",L"results");
st.AssertSucceeded( ) ;
PluginItem nodeItem = in_reg.RegisterICENode(nodeDef);
nodeItem.PutCategories(L"Custom ICENode");
return CStatus::OK;
}SubmitEvaluationPhaseInfoコールバックを実装するには
現在の評価フェーズのために引き出すポートを指定するには、SubmitEvaluationPhaseInfo コールバックが必要です。 このコールバックは ICENodeContext::SetLastEvaluationPhase を使用して現在のフェーズを最終フェーズとしてマークするまで、Softimage によって無限に呼び出されます。
XSIPLUGINCALLBACK CStatus MultiPhaseSample_SubmitEvaluationPhaseInfo( ICENodeContext& in_ctxt )
{
ULONG nPhase = in_ctxt.GetEvaluationPhaseIndex( );
switch( nPhase )
{
case 0:
{
in_ctxt.AddEvaluationPhaseInputPort( ID_IN_condition );
}
break;
case 1:
{
bool bCondition = (bool)in_ctxt.GetUserData();
ULONG nPortToPull = bCondition ? ID_IN_true : ID_IN_false;
in_ctxt.PutUserData( nPortToPull );
in_ctxt.AddEvaluationPhaseInputPort( nPortToPull );
in_ctxt.AddEvaluationPhaseInputPort( ID_IN_points );
// This phase is the last one. All ports specified for phase 1 will be evaluated in multi-threaded batches.
in_ctxt.SetLastEvaluationPhase();
}
break;
}
return CStatus::OK;
}Evaluateコールバックでは、シングルスレッドの中間フェーズの処理とマルチスレッドの最終フェーズを処理できます。
XSIPLUGINCALLBACK CStatus MultiPhaseSample_Evaluate( ICENodeContext& in_ctxt )
{
// Read the current phase.
// Note: ULONG_MAX is returned if the last phase is being processed.
ULONG nPhase = in_ctxt.GetEvaluationPhaseIndex( );
switch( nPhase )
{
case 0:
{
CDataArrayBool conditionData( in_ctxt, ID_IN_condition );
in_ctxt.PutUserData( conditionData[0] );
return CStatus::OK;
}
break;
};
// Process the output port being evaluated in multi-threading.
ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID( );
switch( out_portID )
{
case ID_OUT_results:
{
ULONG nPortToPull = (ULONG)in_ctxt.GetUserData();
CDataArrayFloat scaleValue( in_ctxt, nPortToPull );
float fScaleValue = scaleValue[0];
CDataArrayVector3f resultsData( in_ctxt );
CDataArrayVector3f points( in_ctxt, ID_IN_points );
CIndexSet indexSet( in_ctxt );
for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
resultsData[it] = points[it];
resultsData[it] *= fScaleValue;
}
}
break;
};
return CStatus::OK;
}