Getting the Local Reference Frame

At this time, the SDK does not have an official way to access the local frame reference information. There is, however, a Local Frame Magic Formula for polygon mesh vertices that you can use to evaluate it yourself, or you can use a workaround involving one of the SDK object model’s deprecated interfaces.

| Only the magic formula for polygon mesh vertices is provided because it is often used to compute the displacement from local relative shapes on polygon meshes. For other cases, please use the following workaround.

The deprecated Geometry0D, Geometry1D, and Geometry2D interfaces represent the original versions (implemented in v1.0 but deprecated in v1.5) of the Point, Edge, and Facet interfaces, respectively. Each of these interfaces implements a LocalReferenceFrame method which returns the X, Y, and Z axes of the local reference frame at the specified index of the subcomponent.

You can get these deprecated interfaces through the (also deprecated) Geometry_V1 interface, which is available via the CollectionItem.Obj property.

Ok, so here’s the catch: the LocalReferenceFrame methods use output objects and so are not available to JScript and the C++ API (Python can handle output arguments from methods without difficulty—see Working with Return Values and Output Arguments for more information). As a workaround, you can implement a custom command (in VBScript) to return an array of these values. That command can then be used by JScript or the C++ API to read the local reference frame, as JScript Example: Using the VBS wrapper to get the Local Reference Frame and C++ Example: Using the VBS wrapper to get the Local Reference Frame illustrate, using a custom command implemented like the one in VBScript Example: Implementing a JScript-compliant version of the LocalReferenceFrame methods or VBScript Example: Implementing a C++ API-compliant version of the LocalReferenceFrame methods.

VBScript Example: Implementing a JScript-compliant version of the LocalReferenceFrame methods

This version of this custom command returns an array containing the output arguments exactly as they are returned from the LocalReferenceFrame methods (that is, a safearray containing the following elements: SIVector3, Boolean, SIVector3, Boolean, SIVector3, Boolean).

| The C++ API cannot read the SIVector3 interface and cannot convert it to the CVector3 class, so this version will not work with the C++ API. For a C++ API-compliant version, see VBScript Example: Implementing a C++ API-compliant version of the LocalReferenceFrame methods.

    '
    ' 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 Example: Using the VBS wrapper to get the Local Reference Frame

This example demonstrates how to get the Local Reference Frame information on a cube using JScript. Because JScript cannot handle the output arguments returned by the LocalReferenceFrame methods on the deprecated Geometry0D, Geometry1D, and Geometry2D objects, you must write a custom command in VBScript to extract the information and reformat it for use by JScript. In this example, the expected result is a 1-dimensional safearray containing 3 pairs of SIVector3 and Boolean elements (as implemented in VBScript Example: Implementing a JScript-compliant version of the LocalReferenceFrame methods).

    // 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

VBScript Example: Implementing a C++ API-compliant version of the LocalReferenceFrame methods

The C++ API cannot read the SIVector3 interface and cannot convert it to the CVector3 class, so this version of the custom command returns an array containing the output arguments flattened (that is, each SIVector3 is expanded in place to its x,y,z values).

| Only the implementation is presented here, since all other aspects of the custom command (declaration, initialization) remain the same. See VBScript Example: Implementing a JScript-compliant version of the LocalReferenceFrame methods to see the other callbacks for this command.

    ' 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++ Example: Using the VBS wrapper to get the Local Reference Frame

This example demonstrates how to get the Local Reference Frame information on a cube using the C++ API. Because the C++ API cannot handle the output arguments returned by the LocalReferenceFrame methods on the deprecated Geometry0D, Geometry1D, and Geometry2D objects, you must write a custom command in VBScript to extract the information and reformat it for use by the C++ API. In this example, the expected result is a flat array of 12 elements arranged as 3 quartets of double, double, double, bool elements. Each quartet represents the x.y.z values plus an indicator of the validity for each axis (as implemented in VBScript Example: Implementing a C++ API-compliant version of the LocalReferenceFrame methods).

       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" );
              }
           }

Local Frame Magic Formula

The local reference frame for vertices of polygon meshes is computed in object space, as the following:

• Y = vertex normal This is the same as Geometry0D.Normal or Point.Normal (or Point::GetNormal in the C++ API). To compute it yourself, you have to take the normalized sum of the cross products of the pair of consecutive normalized edge vectors around the vertex.

• X = normalized projection of the first edge vector (starting from current vertex) onto the normal plane.

• Z = cross prod of X and Y.

Autodesk Softimage v7.5