Softimage SDK Programmer's Guide > Working with the SDK > Modeling >

# 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.

Tip

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).

Important

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).

Note

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.