現時点で、SDK にはローカル フレーム リファレンスの情報にアクセスする正式な方法がありません。 ただし、ポリゴン メッシュの頂点用にローカル フレームの便利な式が用意されているので、これを使用してポリゴン メッシュの頂点をユーザ自身で評価することは可能です。また、SDK オブジェクト モデルのいずれかの廃止されたインターフェイスを使った解決策を使用することもできます。
非推奨の Geometry0D、Geometry1D、および Geometry2D インタフェースとは、それぞれ Point、Edge、および Facet インタフェースのオリジナル バージョンを意味します(つまり、オリジナル バージョンの v1.0 で実装されながらも、v1.5 で廃止が決定したものです)。これらのインターフェイスは、サブコンポーネントの指定したインデックスでローカルリファレンスの X、Y、Z 軸を戻す LocalReferenceFrame メソッドをそれぞれに実装します。
これらの廃止されたインタフェースは、CollectionItem.Obj プロパティを介して使用できる Geometry_V1 インタフェース(同じく非推奨)を使って取得できます。
それでは問題点を挙げてみます。LocalReferenceFrame メソッドは出力オブジェクトを使用するので、JScript と C++ API では使用できません(Python はメソッドの出力引数を簡単に処理できます。詳細は「戻り値および出力引数を使って操作する」を参照してください)。解決策として、これらの値の配列を戻すためにカスタム コマンド(VBScript)を実装できます。 このコマンドを使用すると、「JScript の例: VBS ラッパーを使用してローカル リファレンス フレームを取得する」および「C++ の例: VBS ラッパーを使用してローカル リファレンス フレームを取得する」に示すように、「VBScript の例: JScript 準拠バージョンの LocalReferenceFrame メソッドを実装する」または「VBScript の例: C++ API 準拠バージョンの LocalReferenceFrame メソッドを実装する」の例のように実装されたカスタム コマンドを使用して、JScript または C++ API でローカル リファレンス フレームを読み込むことができます。
このバージョンのカスタム コマンドは、LocalReferenceFrame メソッドの戻り値とまったく同じ出力引数を含む配列を戻します(つまり、SIVector3、Boolean、SIVector3、Boolean、SIVector3、Boolean というエレメントを含んだ SafeArray です)。
C++ API では SIVector3 インタフェースを読み取ることができないため、そのインタフェースを CVector3 クラスに変換することができません。そのため、このバージョンは C++ API では機能しません。C++ API 準拠バージョンについては、「VBScript の例: C++ API 準拠バージョンの LocalReferenceFrame メソッドを実装する」を参照してください。
' ' GetLocalReferenceFramePlugin ' ' Registration function XSILoadPlugin( in_reg ) in_reg.Author = "yourname" in_reg.Name = "GetLocalReferenceFramePlugin" in_reg.Email = "yourname@yourcompany.com" in_reg.URL = "www.yourcompany.com" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterCommand "GetLocalReferenceFrame","GetLocalReferenceFrame" XSILoadPlugin = true end function ' De-registration function XSIUnloadPlugin( in_reg ) strPluginName = in_reg.Name Application.LogMessage strPluginName & " has been unloaded." XSIUnloadPlugin = true end function ' Set up command arguments, return value and flags function GetLocalReferenceFrame_Init( ctxt ) dim oCmd set oCmd = ctxt.Source oCmd.Description = "Get Local Reference Frame" oCmd.SetFlag siNoLogging, true oCmd.ReturnValue = true dim oArgs set oArgs = oCmd.Arguments oArgs.AddWithHandler "InputObjs", siArgHandlerCollection oArgs.Add "Index", siArgumentInput, , siInt4 oArgs.Add "Dimension", siArgumentInput, "0", siInt2 GetLocalReferenceFrame_Init = true end function ' Main implementation function GetLocalReferenceFrame_Execute( InputObjs, Index, Dimension ) dim oXDGeometry, aInfoCollection dim oXAxis, oYAxis, oZAxis dim bXAxisValid, bYAxisValid, bZAxisValid set oXAxis = XSIMath.CreateVector3() set oYAxis = XSIMath.CreateVector3() set oZAxis = XSIMath.CreateVector3() ' Make sure input object is valid if TypeName(InputObjs(0)) <> "X3DObject" then set GetLocalReferenceFrame_Execute = Nothing Application.LogMessage( "Input object is not a valid object: " & InputObj.Type ) exit function end if ' Decide which info to get if Dimension = 0 then set oXDGeometry = InputObjs(0).Obj.Geometry0D elseif Dimension = 1 then set oXDGeometry = InputObjs(0).Obj.Geometry1D else set oXDGeometry = InputObjs(0).Obj.Geometry2D end if ' Call the correct method and then use the output arguments to populate the array to return oXDGeometry.LocalReferenceFrame i, oXAxis, bXAxisValid, oYAxis, bYAxisValid, oZAxis, bZAxisValid aInfoCollection = Array( oXAxis, bXAxisValid, oYAxis, bYAxisValid, oZAxis, bZAxisValid ) ' The array returned will be a 1-dimensional SAFEARRAY GetLocalReferenceFrame_Execute = aInfoCollection end function
この例では、JScript を使って立方体のローカル リファレンス フレーム情報を取得する方法を示します。 JScript は Geometry0D、Geometry1D、および Geometry2D という廃止されたオブジェクトの LocalReferenceFrame メソッドが戻す出力引数を処理できないので、JScript で使用できるように情報を抽出し、再フォーマットするために、VBScript でカスタム コマンドを記述する必要があります。 この例では、予想される結果は 3 組の SIVector3 と Boolean エレメントを含んだ 1 次元 SafeArray になります(実装例については、「VBScript の例: JScript 準拠バージョンの LocalReferenceFrame メソッドを実装する」を参照)。
// Create a cube var objItem = CreatePrim( "Cube", "MeshSurface" ); // Get number of vertices in the cube var nbrPoints = objItem.ActivePrimitive.Geometry.Points.Count; // Set up some storage for the local reference frame info var vc3XAxis = XSIMath.CreateVector3(); var booXAxisValid; var vc3YAxis = XSIMath.CreateVector3(); var booYAxisValid; var vc3ZAxis = XSIMath.CreateVector3(); var booZAxisValid; // Get the local reference frame for each point for ( var i=0; i<nbrPoints; i++ ) { var aResults = GetLocalReferenceFrame( objItem, i, 0 ).toArray(); vc3XAxis = aResults[0]; booXAxisValid = aResults[1]; vc3YAxis = aResults[2]; booYAxisValid = aResults[3]; vc3ZAxis = aResults[4]; booZAxisValid = aResults[5]; if ( booXAxisValid ) { Application.LogMessage ( "Component [" + i + "] X axis : " + vc3XAxis.x + " | " + vc3XAxis.y + " | " + vc3XAxis.z ); } else { Application.LogMessage ( "Component [" + i + "] INVALID X axis" ); } if ( booYAxisValid ) { Application.LogMessage ( "Component [" + i + "] Y axis : " + vc3YAxis.x + " | " + vc3YAxis.y + " | " + vc3YAxis.z ); } else { Application.LogMessage ( "Component [" + i + "] INVALID Y axis" ); } if ( booZAxisValid ) { Application.LogMessage ( "Component [" + i + "] Z axis : " + vc3ZAxis.x + " | " + vc3ZAxis.y + " | " + vc3ZAxis.z ); } else { Application.LogMessage ( "Component [" + i + "] INVALID Z axis" ); } } //INFO : Component [0] X axis : 0.408248290463863 | -0.816496580927726 | 0.408248290463863 //INFO : Component [0] Y axis : -0.577350269189626 | -0.577350269189626 | -0.577350269189626 //INFO : Component [0] Z axis : 0.707106781186547 | 0 | -0.707106781186547 //INFO : Component [1] X axis : -0.408248290463863 | 0.408248290463863 | -0.816496580927726 //INFO : Component [1] Y axis : 0.577350269189626 | -0.577350269189626 | -0.577350269189626 //INFO : Component [1] Z axis : -0.707106781186547 | -0.707106781186547 | 0 //INFO : Component [2] X axis : -0.816496580927726 | -0.408248290463863 | 0.408248290463863 //INFO : Component [2] Y axis : -0.577350269189626 | 0.577350269189626 | -0.577350269189626 //INFO : Component [2] Z axis : 0 | -0.707106781186547 | -0.707106781186547 //INFO : Component [3] X axis : -0.408248290463863 | -0.408248290463863 | -0.816496580927726 //INFO : Component [3] Y axis : 0.577350269189626 | 0.577350269189626 | -0.577350269189626 //INFO : Component [3] Z axis : 0.707106781186547 | -0.707106781186547 | 0 //INFO : Component [4] X axis : 0.408248290463863 | -0.816496580927726 | -0.408248290463863 //INFO : Component [4] Y axis : -0.577350269189626 | -0.577350269189626 | 0.577350269189626 //INFO : Component [4] Z axis : -0.707106781186547 | 0 | -0.707106781186547 //INFO : Component [5] X axis : 0.816496580927726 | 0.408248290463863 | -0.408248290463863 //INFO : Component [5] Y axis : 0.577350269189626 | -0.577350269189626 | 0.577350269189626 //INFO : Component [5] Z axis : 0 | -0.707106781186547 | -0.707106781186547 //INFO : Component [6] X axis : -0.816496580927726 | -0.408248290463863 | -0.408248290463863 //INFO : Component [6] Y axis : -0.577350269189626 | 0.577350269189626 | 0.577350269189626 //INFO : Component [6] Z axis : 0 | 0.707106781186547 | -0.707106781186547 //INFO : Component [7] X axis : -0.408248290463863 | 0.816496580927726 | -0.408248290463863 //INFO : Component [7] Y axis : 0.577350269189626 | 0.577350269189626 | 0.577350269189626 //INFO : Component [7] Z axis : 0.707106781186547 | 0 | -0.707106781186547
C++ API では SIVector3 インタフェースを読み取ることができず、CVector3 クラスに変換することができないため、このバージョンのカスタム コマンドは、フラットにした(各 SIVector3 を規則的に x、y、z 値に展開した)出力引数から成る配列を戻します。
このカスタム コマンドのその他の状況(宣言、初期化)はすべて同じままなので、ここでは実装のみを紹介します。 このコマンドのその他のコールバックを確認するには、「VBScript の例: JScript 準拠バージョンの LocalReferenceFrame メソッドを実装する」を参照してください。
' Main implementation function GetLocalReferenceFrame_Execute( InputObjs, Index, Dimension ) dim oXDGeometry, aInfoCollection dim oXAxis, oYAxis, oZAxis dim bXAxisValid, bYAxisValid, bZAxisValid set oXAxis = XSIMath.CreateVector3() set oYAxis = XSIMath.CreateVector3() set oZAxis = XSIMath.CreateVector3() ' Make sure input object is valid if TypeName(InputObjs(0)) <> "X3DObject" then set GetLocalReferenceFrame_Execute = Nothing Application.LogMessage( "Input object is not a valid object: " & InputObj.Type ) exit function end if ' Decide which info to get if Dimension = 0 then set oXDGeometry = InputObjs(0).Obj.Geometry0D elseif Dimension = 1 then set oXDGeometry = InputObjs(0).Obj.Geometry1D else set oXDGeometry = InputObjs(0).Obj.Geometry2D end if ' Call the correct method and then use the output arguments to populate the array to return ' In this case we want to return the actual values of the SIVector3, not the SIVector3 ' itself. This is because the C++ API cannot handle the SIVector3 interface so we need to pass ' the actual x,y,z values. oXDGeometry.LocalReferenceFrame i, oXAxis, bXAxisValid, oYAxis, bYAxisValid, oZAxis, bZAxisValid aInfoCollection = Array( oXAxis.X, oXAxis.Y, oXAxis.Z, bXAxisValid, _ oYAxis.X, oYAxis.Y, oYAxis.Z, bYAxisValid, _ oZAxis.X, oZAxis.Y, oZAxis.Z, bZAxisValid ) ' The array returned will be a 1-dimensional SAFEARRAY GetLocalReferenceFrame_Execute = aInfoCollection end function
この例では、C++ API を使って立方体のローカル リファレンス フレーム情報を取得する方法を示します。 C++ API では Geometry0D、Geometry1D、および Geometry2D という廃止されたオブジェクトの LocalReferenceFrame メソッドが戻す出力引数を処理できないので、C++ API で使用できるように情報を抽出して再フォーマットするように、VBScript でカスタム コマンドを記述する必要があります。 この例の場合、予想結果は 12 個のエレメントを持つフラットな配列になります(double、double、double、bool という 4 つのエレメントを 1 組とするものを合計 3 つ並べた配列です)。 各組は x.y.z 値と各軸の有効性を示すインジケータを表します(実装例については、「VBScript の例: C++ API 準拠バージョンの LocalReferenceFrame メソッドを実装する」を参照)。
Application app; Model root = app.GetActiveSceneRoot(); // Create a cube X3DObject objItem; root.AddGeometry( L"Cube", L"MeshSurface", L"MyCube", objItem ); // Get number of vertices in the cube CPointRefArray refPoints = objItem.GetActivePrimitive().GetGeometry().GetPoints(); LONG nbrPoints = refPoints.GetCount(); // Set up the arguments for the custom command CValueArray ccArgs(3); CValue ccOut; ccArgs[0] = objItem; ccArgs[2] = CValue(0.0); // Get the local reference frame for each point for ( LONG i=0; i<nbrPoints; ++i ) { // Run the command (you only need to change the index number for this example) ccArgs[1] = i; app.ExecuteCommand( L"GetLocalReferenceFrame", ccArgs, ccOut ); // Grab the output arguments from the returned array if ( ccOut.m_t == CValue::siArray ) { MATH::CVector3 vc3XAxis; MATH::CVector3 vc3YAxis; MATH::CVector3 vc3ZAxis; bool booXAxisValid; bool booYAxisValid; bool booZAxisValid; CValueArray aResults(ccOut); vc3XAxis.Set( aResults[0], aResults[1], aResults[2] ); // XAxis booXAxisValid = aResults[3]; // XAxisValid vc3YAxis.Set( aResults[4], aResults[5], aResults[6] ); // YAxis booYAxisValid = aResults[7]; // YAxisValid vc3ZAxis.Set( aResults[8], aResults[9], aResults[10] ); // ZAxis booZAxisValid = aResults[11]; // ZAxisValid // Log the information in Softimage if ( booXAxisValid ) { app.LogMessage ( L"Component [" + CString(i) + L"] X axis : " + CString(vc3XAxis.GetX()) + L" | " + CString(vc3XAxis.GetY()) + L" | " + CString(vc3XAxis.GetZ()) ); } else { app.LogMessage ( L"Component [" + CString(i) + L"] INVALID X axis" ); } if ( booYAxisValid ) { app.LogMessage ( L"Component [" + CString(i) + L"] Y axis : " + CString(vc3YAxis.GetX()) + L" | " + CString(vc3YAxis.GetY()) + L" | " + CString(vc3YAxis.GetZ()) ); } else { app.LogMessage ( L"Component [" + CString(i) + L"] INVALID Y axis" ); } if ( booZAxisValid ) { app.LogMessage ( L"Component [" + CString(i) + L"] Z axis : " + CString(vc3ZAxis.GetX()) + L" | " + CString(vc3ZAxis.GetY()) + L" | " + CString(vc3ZAxis.GetZ()) ); } else { app.LogMessage ( L"Component [" + CString(i) + L"] INVALID Z axis" ); } }
ポリゴン メッシュ頂点のローカル リファレンス フレームは、次のようにオブジェクト空間で計算されます。
Y = 頂点の法線 これは Geometry0D.Normal または Point.Normal(C++ API の場合は Point::GetNormal)と同じです。頂点の法線をユーザ自身で算出するには、頂点を基点とする隣どうしの正規化エッジ ベクトルの外積をそれぞれすべて算出し、これらの外積の和を求め、その和を正規化することが必要です。