マルチフェーズ プロセス モデルでは、シングル フェーズまたはマルチ フェーズのどちらでもカスタム ノードを使用して入力データを処理できます。各フェーズには処理する入力ポートを類似したコンテキストにグループ化して含めることができます。 マルチ フェーズ評価モデルの主な目的は、入力ポートが評価される方法を最適化することです。 たとえば、フェーズ 0 で 1 つのポートを引き出します。次に、それ以降のフェーズで引き出すポートは、フェーズ 0 で読み取ったデータに基づいて決定することができます。
入力コンテキスト タイプを自由に指定できます。ロード時に Softimage によって検証が実行されることはありません。 たとえば、トポロジが異なるまたはデータ セットが異なる(法線とポイントなど)2 つのオブジェクトのポイントへ、同じオブジェクトから接続するように選択できます。
引き出すポートは同じコンテキスト タイプを共有する必要があります。共有しない場合はエラーが発生します。 ただし、Singleton コンテキストとフェーズ コンテキストを混在させることはできます。
最終フェーズで引き出すポートは出力ポートのコンテキスト タイプと同一である必要があります。同一でない場合はエラーが発生します。
SubmitEvaluationPhaseInfo コールバックを渡す必要があります。
次のワークフローは、一般的なマルチフェーズ カスタム ICENode の実装方法を示しています。詳細については、Softimage SDK のインストール ディレクトリにある RandomGridGenerator のサンプルを参照してください。
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 コールバックが必要です。 このコールバックは 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; }