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