Open Inventor Release 2024.2.0
 
Loading...
Searching...
No Matches
Transformations

Unlike other property nodes, transformation nodes do not replace the current geometric transformation element in the action state. Instead, they have a cumulative effect on the current geometric transformation. In Cumulative Effect of Transformation Nodes , for example, the transformations in node xfm1 are applied first, followed by the transformations in node xfm2.

Cumulative Effect of Transformation Nodes

The cube is affected by only the transformation in xfm1. The sphere, however, is affected by both xfm1 and xfm2.

SoTransform Node

An SoTransform node includes the following fields:

translation (SoSFVec3f) the translation in x, y, and z. The default value is [0.0 0.0 0.0].
rotation (SoSFRotation) the rotation in terms of an axis and an angle. The default value is [0.0 0.0 1.0], 0.0.
scaleFactor (SoSFVec3f) the scaling factor in x, y, and z. The default value for this field is [1.0 1.0 1.0].
scaleOrientation (SoSFRotation) the rotation to apply before the scale is applied. The default value is [0.0 0.0 1.0], 0.0.
center (SoSFVec3f) the center point for rotation and scaling. The default value for this field is [0.0 0.0 0.0].

If you are using only one of the fields in an SoTransform node, you can substitute the corresponding “lightweight” version. For rotations, use SoRotation or SoRotationXYZ ; for translations, use SoTranslation ; and for scaling, use SoScale.

Order of Transformations

Within each SoTransform node, the fields are applied so that the last field in the node (the center) affects the shape object first. The order is first the center, followed by the scale orientation, the scaling factor, the rotation, and the translation.

Two Groups with Transformations in Different Order and Effects of Ordering Transformation Fields show how different ordering of transformations produces different results. At the left of Effects of Ordering Transformation Fields , the temple is scaled, rotated, and then translated. The transform node closest to the shape object affects the object first. You thus need to read backward through the code to see how the effects of the transformations are felt. At the right of Effects of Ordering Transformation Fields , the temple is rotated, then scaled and translated. Changing the Order of Transformations shows the code for the two sets of transformations.

Two Groups with Transformations in Different Order

Effects of Ordering Transformation Fields

Changing the Order of Transformations

Example : Changing the Order of Transformations

C++ :

#include <Inventor/SoDB.h>
#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoRotationXYZ.h>
#include <Inventor/nodes/SoScale.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoTranslation.h>
main( int, char** argv )
{
// Initialize Inventor and Xt
Widget myWindow = SoXt::init( argv[0] );
if ( myWindow == NULL )
exit( 1 );
SoSeparator* root = new SoSeparator;
root->ref();
// Create two separators, for left and right objects.
SoSeparator* leftSep = new SoSeparator;
SoSeparator* rightSep = new SoSeparator;
root->addChild( leftSep );
root->addChild( rightSep );
// Create the transformation nodes.
SoTranslation* leftTranslation = new SoTranslation;
SoTranslation* rightTranslation = new SoTranslation;
SoRotationXYZ* myRotation = new SoRotationXYZ;
SoScale* myScale = new SoScale;
// Fill in the values.
leftTranslation->translation.setValue( -1.0, 0.0, 0.0 );
rightTranslation->translation.setValue( 1.0, 0.0, 0.0 );
myRotation->angle = M_PI / 2; // 90 degrees
myRotation->axis = SoRotationXYZ::X;
myScale->scaleFactor.setValue( 2., 1., 3. );
// Add transforms to the scene.
leftSep->addChild( leftTranslation ); // left graph
leftSep->addChild( myRotation ); // then rotated
leftSep->addChild( myScale ); // first scaled
rightSep->addChild( rightTranslation ); // right graph
rightSep->addChild( myScale ); // then scaled
rightSep->addChild( myRotation ); // first rotated
// Read an object from file. (as in example 4.2.Lights)
SoInput myInput;
if ( !myInput.openFile( "temple.iv" ) )
return ( 1 );
SoSeparator* fileContents = SoDB::readAll( &myInput );
if ( fileContents == NULL )
return ( 1 );
// Add an instance of the object under each separator.
leftSep->addChild( fileContents );
rightSep->addChild( fileContents );
// Construct a renderArea and display the scene.
SoXtExaminerViewer* myViewer = new SoXtExaminerViewer( myWindow );
myViewer->setSceneGraph( root );
myViewer->setTitle( "Transform Ordering" );
myViewer->viewAll();
myViewer->show();
SoXt::show( myWindow );
SoXt::mainLoop();
}

C# :

using OIV.Inventor.Nodes;
using OIV.Inventor.Win;
using OIV.Inventor.Win.Viewers;
using OIV.Inventor;
namespace _05_6_TransformOrdering {
public partial class MainForm : Form
{
SoWinExaminerViewer myViewer;
public MainForm()
{
InitializeComponent();
CreateSample();
}
public void CreateSample()
{
SoSeparator root = new SoSeparator();
// Create two separators, for left and right objects.
SoSeparator leftSep = new SoSeparator();
SoSeparator rightSep = new SoSeparator();
root.AddChild( leftSep );
root.AddChild( rightSep );
// Create the transformation nodes
SoTranslation leftTranslation = new SoTranslation();
SoTranslation rightTranslation = new SoTranslation();
SoRotationXYZ myRotation = new SoRotationXYZ();
SoScale myScale = new SoScale();
// Fill in the values
leftTranslation.translation.Value = new SbVec3f( -1.0f, 0.0f, 0.0f );
rightTranslation.translation.Value = new SbVec3f( 1.0f, 0.0f, 0.0f );
myRotation.angle.Value = ( float )( Math.PI / 2.0f ); // 90 degrees
myRotation.axis.Value = SoRotationXYZ.AxisType.X;
myScale.scaleFactor.Value = new SbVec3f( 2.0f, 1.0f, 3.0f );
// Add transforms to the scene.
leftSep.AddChild( leftTranslation ); // left graph
leftSep.AddChild( myRotation ); // then rotated
leftSep.AddChild( myScale ); // first scaled
rightSep.AddChild( rightTranslation ); // right graph
rightSep.AddChild( myScale ); // then scaled
rightSep.AddChild( myRotation ); // first rotated
// Read an object from file. (as in example 4.2.Lights)
SoInput myInput = new SoInput();
myInput.OpenFile( "../../../../../data/temple.iv" );
SoSeparator fileContents = SoDB.ReadAll( myInput );
// Add an instance of the object under each separator.
leftSep.AddChild( fileContents );
rightSep.AddChild( fileContents );
// Construct a renderArea and display the scene.
myViewer = new SoWinExaminerViewer( this, "", true, SoWinFullViewer.BuildFlags.BUILD_ALL, SoWinViewer.Types.BROWSER );
myViewer.SetSceneGraph( root );
myViewer.SetTitle( "Transform Ordering" );
myViewer.ViewAll();
}
}
} // namespace _05_6_TransformOrdering

Java :

import tools.*;
import com.openinventor.inventor.nodes.*;
import com.openinventor.inventor.*;
import com.openinventor.inventor.awt.*;
import java.awt.*;
public class Main extends DemoInventor
{
public static void main( String[] args )
{
Main applet = new Main();
DemoInventor.isAnApplet = false;
applet.start();
demoMain( applet, "Transform Ordering" );
}
public void start()
{
super.start();
// Create two separators, for left and right objects.
SoSeparator leftSep = new SoSeparator();
SoSeparator rightSep = new SoSeparator();
// Create the transformation nodes
SoTranslation leftTranslation = new SoTranslation();
SoTranslation rightTranslation = new SoTranslation();
SoRotationXYZ myRotation = new SoRotationXYZ();
SoScale myScale = new SoScale();
// Fill in the values
leftTranslation.translation.setValue( -1.0f, 0.0f, 0.0f );
rightTranslation.translation.setValue( 1.0f, 0.0f, 0.0f );
myRotation.angle.setValue( ( float )java.lang.Math.PI / 2.0f ); // 90 degrees
myRotation.axis.setValue( SoRotationXYZ.X );
myScale.scaleFactor.setValue( 2.0f, 1.0f, 3.0f );
// Read an object from file. (as in example 4.2.Lights)
SoInput myInput = new SoInput();
if ( !myInput.openFile( m_prefix + "../../../../data/models/temple.iv" ) )
System.exit( 1 );
SoSeparator fileContents = SoDB.readAll( myInput );
if ( fileContents == null )
System.exit( 1 );
SoSeparator root = new SoSeparator();
{ // Assemble scene graph
root.addChild( leftSep );
root.addChild( rightSep );
// Add transforms to the scene.
leftSep.addChild( leftTranslation ); // left graph
leftSep.addChild( myRotation ); // then rotated
leftSep.addChild( myScale ); // first scaled
rightSep.addChild( rightTranslation ); // right graph
rightSep.addChild( myScale ); // then scaled
rightSep.addChild( myRotation ); // first rotated
// Add an instance of the object under each separator.
leftSep.addChild( fileContents );
rightSep.addChild( fileContents );
}
// Construct a renderArea and display the scene.
SwSimpleViewer myViewer = new SwSimpleViewer();
myViewer.setSceneGraph( root );
setLayout( new BorderLayout() );
add( myViewer, BorderLayout.CENTER );
}
}

Non-linear projection