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

You can use manipulators in your application in various ways:

  • You can use the replaceNode() method to replace certain kinds of nodes in the scene graph with an editable version. When the user is finished manipulating the node, use the replaceManip() method to restore the original node to the scene graph.
  • You can write your own callback functions to use the field values of the manipulator. The callback functions described in Callback Functions can be used for any manipulator. (Recall that these functions belong to the dragger, so you need to call getDragger() before using them.) You can also combine use of these two techniques. For example, you can use replaceNode() to replace an SoTransform with a manipulator. Then you can use a value-changed callback to notify the application when any of the manipulator's dragger fields changes, and the application can use this new value, if desired.

The following sections describe both of these techniques in more detail.

Replacing a Node with a Manipulator

To use any manipulator in an application, follow these basic steps:

  1. Construct the manipulator.
  2. Reference it if you plan on reusing it.
  3. Replace the node in the scene graph with the manipulator. Manipulators derived from SoTransform, such as the handle box and trackball, replace an SoTransform node. An SoDirectionalLight- Manip replaces an SoDirectionalLight node, an SoPointLightManip replaces an SoPointLight node, and so on.

Replacing a Node

The replaceNode() method takes a path as an argument:

C++ :

replaceNode( SoPath* p )

C# :

ReplaceNode( SoPath* p )

Java :

replaceNode( SoPath* p )

The path is supplied by the application. For example, Specifying the Path to the Target Node shows the path to a target SoTransform node. When a transform manipulator replaces this node, editing the manipulator will affect cube2 in the scene graph.

Manipulators subclassed from SoTransformManip use special nodes to maintain their shape (so that the trackball remains spherical, for example) and to ensure that they surround the shape objects they affect. These nodes are described in The Inventor Toolmaker.

Specifying the Path to the Target Node

Removing the Manipulator

To remove the manipulator from the scene graph:

  1. Use the replaceManip() method to restore the original node to the scene graph. In the example, the field values from the manipulator are copied into the transform node.
  2. Use unref() on the manipulator so that it will be deleted. Because the manipulator methods replaceManip() and replaceNode() exchange the new node for the tail of the given path, you can reuse the path for subsequent calls to these methods.

For example, if we begin with:

C++ :

myManip = new SoTrackballManip;
myPathToTransform = createPathtoTransform( pickPath );

C# :

SoTrackballManip myManip = new SoTrackballManip();
SoPath myPathToTransform = createPathtoTransform( pickPath );

Java :

SoTrackballManip myManip = new SoTrackballManip();
SoPath myPathToTransform = createPathtoTransform( pickPath );

Then we can call:

C++ :

myManip->replaceNode( myPathToTransform );

C# :

myManip.ReplaceNode( myPathToTransform );

Java :

myManip.replaceNode( myPathToTransform );

to put the manipulator at the end of the path.

Later, we can call

C++ :

myManip->replaceManip( myPathToTransform, new SoTransform );

C# :

myManip.ReplaceManip( myPathToTransform, new SoTransform() );

Java :

myManip.replaceManip( myPathToTransform, new SoTransform() );

to remove the manipulator and replace it with a transform.

1.

Using the replaceNode() Method

Using Manipulators to Transform Objects displays a cube, a sphere, and a lamp. The lamp is read from a file and inserted as the “contents” part of an SoWrapperKit. When the user picks the cube, a trackball replaces the transform node that affects the cube. When the user picks the sphere, a handle box replaces the transform node that affects the sphere. When the user picks the lamp, a transform box replaces the “transform” part of the wrapper kit containing the lamp. Adding Manipulators to a Scene shows an image created by this program. This example shows the following techniques:

  • Using replaceNode() and replaceManip() to make certain nodes in the scene graph editable and to restore the original nodes when manipulation finishes
  • Using selection callbacks (see Handling Events and Selection)

Example : Using Manipulators to Transform Objects

C++ :

// Note that for illustration purposes, the
// cube and SoWrapperKit already have transform nodes
// associated with them; the sphere does not. In all cases,
// the routine createTransformPath() is used to find the
// transform node that affects the picked object.
#include <Inventor/SoDB.h>
#include <Inventor/SoInput.h>
#include <Inventor/manips/SoHandleBoxManip.h>
#include <Inventor/manips/SoTrackballManip.h>
#include <Inventor/manips/SoTransformBoxManip.h>
#include <Inventor/nodekits/SoWrapperKit.h>
#include <Inventor/nodes/SoCamera.h>
#include <Inventor/nodes/SoCube.h>
#include <Inventor/nodes/SoGroup.h>
#include <Inventor/nodes/SoLight.h>

Adding Manipulators to a Scene

C++ :

#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoSelection.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoTransform.h>
#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
// function prototypes
void selectionCallback( void*, SoPath* );
void deselectionCallback( void*, SoPath* );
void dragStartCallback( void*, SoDragger* );
void dragFinishCallback( void*, SoDragger* );
// global data
SoSeparator* root;
SoHandleBoxManip* myHandleBox;
SoTrackballManip* myTrackball;
SoTransformBoxManip* myTransformBox;
SoPath* handleBoxPath = NULL;
SoPath* trackballPath = NULL;
SoPath* transformBoxPath = NULL;
main( int, char** argv )
{
// Initialize Inventor and Xt
Widget myWindow = SoXt::init( argv[0] );
if ( myWindow == NULL )
exit( 1 );
// Create and set up the selection node
SoSelection* selectionRoot = new SoSelection;
selectionRoot->ref();
selectionRoot->addSelectionCallback( selectionCallback, NULL );
selectionRoot->addDeselectionCallback( deselectionCallback, NULL );
// Create the scene graph
root = new SoSeparator;
selectionRoot->addChild( root );
// Read a file into contents of SoWrapperKit
// Translate it to the right.
SoWrapperKit* myWrapperKit = new SoWrapperKit;
root->addChild( myWrapperKit );
SoInput myInput;
if ( !myInput.openFile( "luxo.iv" ) )
return ( 1 );
SoSeparator* objectFromFile = SoDB::readAll( &myInput );
if ( objectFromFile == NULL )
return ( 1 );
myWrapperKit->setPart( "contents", objectFromFile );
myWrapperKit->set( "transform { translation 3 -1 0 }" );
SoMaterial* wrapperMat = ( SoMaterial* )myWrapperKit->getPart( "material", TRUE );
wrapperMat->diffuseColor.setValue( .8, .8, .8 );
// Create a cube with its own transform.
SoSeparator* cubeRoot = new SoSeparator;
SoTransform* cubeXform = new SoTransform;
cubeXform->translation.setValue( -4, 0, 0 );
root->addChild( cubeRoot );
cubeRoot->addChild( cubeXform );
SoMaterial* cubeMat = new SoMaterial;
cubeMat->diffuseColor.setValue( .8, .8, .8 );
cubeRoot->addChild( cubeMat );
cubeRoot->addChild( new SoCube );
// Add a sphere node without a transform
// (one will be added when we attach the manipulator)
SoSeparator* sphereRoot = new SoSeparator;
SoMaterial* sphereMat = new SoMaterial;
root->addChild( sphereRoot );
sphereRoot->addChild( sphereMat );
sphereRoot->addChild( new SoSphere );
sphereMat->diffuseColor.setValue( .8, .8, .8 );
// Create the manipulators
myHandleBox = new SoHandleBoxManip;
myHandleBox->ref();
myTrackball = new SoTrackballManip;
myTrackball->ref();
myTransformBox = new SoTransformBoxManip;
myTransformBox->ref();
// Get the draggers and add callbacks to them. Note
// that you don't put callbacks on manipulators. You put
// them on the draggers which handle events for them.
SoDragger* myDragger;
myDragger = myTrackball->getDragger();
myDragger->addStartCallback( dragStartCallback, cubeMat );
myDragger->addFinishCallback( dragFinishCallback, cubeMat );
myDragger = myHandleBox->getDragger();
myDragger->addStartCallback( dragStartCallback, sphereMat );
myDragger->addFinishCallback( dragFinishCallback, sphereMat );
myDragger = myTransformBox->getDragger();
myDragger->addStartCallback( dragStartCallback, wrapperMat );
myDragger->addFinishCallback( dragFinishCallback, wrapperMat );
SoXtExaminerViewer* myViewer = new SoXtExaminerViewer( myWindow );
myViewer->setSceneGraph( selectionRoot );
myViewer->setTitle( "Attaching Manipulators" );
myViewer->show();
myViewer->viewAll();
SoXt::show( myWindow );
SoXt::mainLoop();
}
// Is this node of a type that is influenced by transforms?
SbBool
isTransformable( SoNode* myNode )
{
if ( myNode->isOfType( SoGroup::getClassTypeId() ) || myNode->isOfType( SoShape::getClassTypeId() ) ||
myNode->isOfType( SoCamera::getClassTypeId() ) || myNode->isOfType( SoLight::getClassTypeId() ) )
return TRUE;
else
return FALSE;
}
// Create a path to the transform node that affects the tail
// of the input path. Three possible cases:
// [1] The path-tail is a node kit. Just ask the node kit for
// a path to the part called "transform"
// [2] The path-tail is NOT a group. Search siblings of path
// tail from right to left until you find a transform. If
// none is found, or if another transformable object is
// found (shape,group,light,or camera), then insert a
// transform just to the left of the tail. This way, the
// manipulator only affects the selected object.
// [3] The path-tail IS a group. Search its children left to
// right until a transform is found. If a transformable
// node is found first, insert a transform just left of
// that node. This way the manip will affect all nodes
// in the group.
SoPath*
createTransformPath( SoPath* inputPath )
{
int pathLength = inputPath->getLength();
if ( pathLength < 2 ) // Won't be able to get parent of tail
return NULL;
SoNode* tail = inputPath->getTail();
// CASE 1: The tail is a node kit.
// Nodekits have built in policy for creating parts.
// The kit copies inputPath, then extends it past the
// kit all the way down to the transform. It creates the
// transform if necessary.
if ( tail->isOfType( SoBaseKit::getClassTypeId() ) )
{
SoBaseKit* kit = ( SoBaseKit* )tail;
return kit->createPathToPart( "transform", TRUE, inputPath );
}
SoTransform* editXf = NULL;
SoGroup* parent;
SbBool existedBefore = FALSE;
// CASE 2: The tail is not a group.
SbBool isTailGroup;
isTailGroup = tail->isOfType( SoGroup::getClassTypeId() );
if ( !isTailGroup )
{
// 'parent' is node above tail. Search under parent right
// to left for a transform. If we find a 'movable' node
// insert a transform just left of tail.
parent = ( SoGroup* )inputPath->getNode( pathLength - 2 );
int tailIndx = parent->findChild( tail );
for ( int i = tailIndx; ( i >= 0 ) && ( editXf == NULL ); i-- )
{
SoNode* myNode = parent->getChild( i );
if ( myNode->isOfType( SoTransform::getClassTypeId() ) )
editXf = ( SoTransform* )myNode;
else if ( i != tailIndx && ( isTransformable( myNode ) ) )
break;
}
if ( editXf == NULL )
{
existedBefore = FALSE;
editXf = new SoTransform;
parent->insertChild( editXf, tailIndx );
}
else
existedBefore = TRUE;
}
// CASE 3: The tail is a group.
else
{
// Search the children from left to right for transform
// nodes. Stop the search if we come to a movable node
// and insert a transform before it.
parent = ( SoGroup* )tail;
for ( int i = 0; ( i < parent->getNumChildren() ) && ( editXf == NULL ); i++ )
{
SoNode* myNode = parent->getChild( i );
if ( myNode->isOfType( SoTransform::getClassTypeId() ) )
editXf = ( SoTransform* )myNode;
else if ( isTransformable( myNode ) )
break;
}
if ( editXf == NULL )
{
existedBefore = FALSE;
editXf = new SoTransform;
parent->insertChild( editXf, i );
}
else
existedBefore = TRUE;
}
// Create 'pathToXform.' Copy inputPath, then make last
// node be editXf.
SoPath* pathToXform = NULL;
pathToXform = inputPath->copy();
pathToXform->ref();
if ( !isTailGroup ) // pop off the last entry.
pathToXform->pop();
// add editXf to the end
int xfIndex = parent->findChild( editXf );
pathToXform->append( xfIndex );
pathToXform->unrefNoDelete();
return ( pathToXform );
}
// This routine is called when an object
// gets selected. We determine which object
// was selected, then call replaceNode()
// to replace the object's transform with
// a manipulator.
void
selectionCallback( void*, // user data is not used
SoPath* selectionPath )
{
// Attach the manipulator.
// Use the convenience routine to get a path to
// the transform that affects the selected object.
SoPath* xformPath = createTransformPath( selectionPath );
if ( xformPath == NULL )
return;
xformPath->ref();
// Attach the handle box to the sphere,
// the trackball to the cube
// or the transformBox to the wrapperKit
if ( selectionPath->getTail()->isOfType( SoSphere::getClassTypeId() ) )
{
handleBoxPath = xformPath;
myHandleBox->replaceNode( xformPath );
}
else if ( selectionPath->getTail()->isOfType( SoCube::getClassTypeId() ) )
{
trackballPath = xformPath;
myTrackball->replaceNode( xformPath );
}
else if ( selectionPath->getTail()->isOfType( SoWrapperKit::getClassTypeId() ) )
{
transformBoxPath = xformPath;
myTransformBox->replaceNode( xformPath );
}
}
// This routine is called whenever an object gets
// deselected. It detaches the manipulator from
// the transform node, and removes it from the
// scene graph that will not be visible.
void
deselectionCallback( void*, // user data is not used
SoPath* deselectionPath )
{
if ( deselectionPath->getTail()->isOfType( SoSphere::getClassTypeId() ) )
{
myHandleBox->replaceManip( handleBoxPath, NULL );
handleBoxPath->unref();
}
else if ( deselectionPath->getTail()->isOfType( SoCube::getClassTypeId() ) )
{
myTrackball->replaceManip( trackballPath, NULL );
trackballPath->unref();
}
else if ( deselectionPath->getTail()->isOfType( SoWrapperKit::getClassTypeId() ) )
{
myTransformBox->replaceManip( transformBoxPath, NULL );
transformBoxPath->unref();
}
}
// This is called when a manipulator is
// about to begin manipulation.
void
dragStartCallback( void* myMaterial, // user data
SoDragger* ) // callback data not used
{
( ( SoMaterial* )myMaterial )->diffuseColor = SbColor( 1, .2, .2 );
}
// This is called when a manipulator is
// done manipulating.
void
dragFinishCallback( void* myMaterial, // user data
SoDragger* ) // callback data not used
{
( ( SoMaterial* )myMaterial )->diffuseColor = SbColor( .8, .8, .8 );
}

C# :

Java :

package inventor.mentor.attachManip;
import tools.*;
import com.openinventor.inventor.nodes.*;
import com.openinventor.inventor.manips.*;
import com.openinventor.inventor.*;
import com.openinventor.inventor.draggers.*;
import com.openinventor.inventor.misc.callbacks.*;
import com.openinventor.inventor.awt.*;
import java.awt.*;
public class Main extends DemoInventor
{
SoHandleBoxManip myHandleBox = new SoHandleBoxManip();
SoTrackballManip myTrackball = new SoTrackballManip();
SoTransformBoxManip myTransformBox = new SoTransformBoxManip();
SoPath handleBoxPath = null;
SoPath trackballPath = null;
SoPath transformBoxPath = null;
SoMaterial cubeMat = new SoMaterial();
SoMaterial sphereMat = new SoMaterial();
SoMaterial coneMat = new SoMaterial();
public static void main( String[] args )
{
Main applet = new Main();
DemoInventor.isAnApplet = false;
applet.start();
demoMain( applet, "Attaching Manipulators" );
}
public void start()
{
super.start();
// create and set up the selection node
SoSelection selectionRoot = new SoSelection();
// Create a cone
SoSeparator coneRoot = new SoSeparator();
SoTransform coneTrans = new SoTransform();
coneTrans.translation.setValue( 3, 0, 0 );
coneMat.diffuseColor.setValue( 0.8f, 0.8f, 0.8f );
{
coneRoot.addChild( coneTrans );
coneRoot.addChild( coneMat );
coneRoot.addChild( new SoCone() );
}
// Create a cube with its own transform.
SoSeparator cubeRoot = new SoSeparator();
SoTransform cubeXform = new SoTransform();
cubeXform.translation.setValue( -3.0f, 0.0f, 0.0f );
cubeMat.diffuseColor.setValue( 0.8f, 0.8f, 0.8f );
{
cubeRoot.addChild( cubeXform );
cubeRoot.addChild( cubeMat );
cubeRoot.addChild( new SoCube() );
}
// add a sphere node without a transform
// (one will be added when we attach the manipulator)
SoSeparator sphereRoot = new SoSeparator();
sphereMat.diffuseColor.setValue( 0.8f, 0.8f, 0.8f );
{
sphereRoot.addChild( sphereMat );
sphereRoot.addChild( new SoSphere() );
}
// create the scene graph
SoSeparator root = new SoSeparator();
{ // assemble scene graph
root.addChild( coneRoot );
root.addChild( cubeRoot );
root.addChild( sphereRoot );
}
// Get the draggers and add callbacks to them. Note
// that you don't put callbacks on manipulators. You put
// them on the draggers which handle events for them.
SoDragger myDragger = myTrackball.getDragger();
myDragger.addStartCallback( new DragStartCallback( cubeMat ), null );
myDragger.addFinishCallback( new DragFinishCallback( cubeMat ), null );
myDragger = myHandleBox.getDragger();
myDragger.addStartCallback( new DragStartCallback( sphereMat ), null );
myDragger.addFinishCallback( new DragFinishCallback( sphereMat ), null );
myDragger = myTransformBox.getDragger();
myDragger.addStartCallback( new DragStartCallback( coneMat ), null );
myDragger.addFinishCallback( new DragFinishCallback( coneMat ), null );
{ // Assemble scene graph
selectionRoot.addSelectionCallback( new SelectionCallback(), null );
selectionRoot.addDeselectionCallback( new DeselectionCallback(), null );
selectionRoot.addChild( root );
}
SwSimpleViewer myViewer = new SwSimpleViewer();
myViewer.setSceneGraph( selectionRoot );
setLayout( new BorderLayout() );
add( myViewer, BorderLayout.CENTER );
}
// Is this node of a type that is influenced by transforms?
boolean
isTransformable( SoNode myNode )
{
if ( myNode instanceof SoGroup || myNode instanceof SoShape || myNode instanceof SoCamera || myNode instanceof SoLight )
return true;
else
return false;
}
SoPath
createTransformPath( SoPath inputPath )
{
int pathLength = inputPath.regular.getLength();
if ( pathLength < 2 ) // Won't be able to get parent of tail
return null;
SoNode tail = inputPath.regular.getTail();
// CASE 1: The tail is a node kit.
// Nodekits have built in policy for creating parts.
// The kit copies inputPath, then extends it past the
// kit all the way down to the transform. It creates the
// transform if necessary.
// if (tail instanceof SoBaseKit)
// {
// SoBaseKit kit = (SoBaseKit)tail;
// return kit.createPathToPart("transform", true, inputPath);
// }
SoTransform editXf = null;
SoGroup parent;
boolean existedBefore = false;
// CASE 2: The tail is not a group.
boolean isTailGroup;
isTailGroup = tail instanceof SoGroup;
if ( !isTailGroup )
{
// 'parent' is node above tail. Search under parent right
// to left for a transform. If we find a 'movable' node
// insert a transform just left of tail.
parent = ( SoGroup )inputPath.regular.getNode( pathLength - 2 );
int tailIndx = parent.findChild( tail );
for ( int i = tailIndx; ( i >= 0 ) && ( editXf == null ); i-- )
{
SoNode myNode = parent.getChild( i );
if ( myNode instanceof SoTransform )
editXf = ( SoTransform )myNode;
else if ( i != tailIndx && ( isTransformable( myNode ) ) )
break;
}
if ( editXf == null )
{
existedBefore = false;
editXf = new SoTransform();
parent.insertChild( editXf, tailIndx );
}
else
existedBefore = true;
}
// CASE 3: The tail is a group.
else
{
// Search the children from left to right for transform
// nodes. Stop the search if we come to a movable node.
// and insert a transform before it.
int i;
parent = ( SoGroup )tail;
for ( i = 0; ( i < parent.getNumChildren() ) && ( editXf == null ); i++ )
{
SoNode myNode = parent.getChild( i );
if ( myNode instanceof SoTransform )
editXf = ( SoTransform )myNode;
else if ( isTransformable( myNode ) )
break;
}
if ( editXf == null )
{
existedBefore = false;
editXf = new SoTransform();
parent.insertChild( editXf, i );
}
else
existedBefore = true;
}
// Create 'pathToXform.' Copy inputPath, then make last
// node be editXf.
SoPath pathToXform = null;
pathToXform = inputPath.regular.copy( 0 );
if ( !isTailGroup ) // pop off the last entry.
pathToXform.regular.pop();
// add editXf to the end
int xfIndex = parent.findChild( editXf );
pathToXform.regular.append( xfIndex );
return ( pathToXform );
}
class SelectionCallback extends SoSelectionPathCB
{
public void invoke( SoPath path )
{
// Attach the manipulator.
// Use the convenience routine to get a path to
// the transform that effects the selected object.
SoPath xformPath = createTransformPath( path );
if ( xformPath == null )
return;
// Attach the handle box to the sphere,
// the trackball to the cube
// or the transformBox to the wrapperKit
if ( path.regular.getTail() instanceof SoSphere )
{
handleBoxPath = xformPath;
myHandleBox.replaceNode( xformPath );
}
else if ( path.regular.getTail() instanceof SoCube )
{
trackballPath = xformPath;
myTrackball.replaceNode( xformPath );
}
else if ( path.regular.getTail() instanceof SoCone )
{
transformBoxPath = xformPath;
myTransformBox.replaceNode( xformPath );
}
}
}
class DeselectionCallback extends SoSelectionPathCB
{
public void invoke( SoPath path )
{
if ( path.regular.getTail() instanceof SoSphere )
myHandleBox.replaceManip( handleBoxPath, new SoTransform() );
else if ( path.regular.getTail() instanceof SoCube )
myTrackball.replaceManip( trackballPath, new SoTransform() );
else if ( path.regular.getTail() instanceof SoCone )
myTransformBox.replaceManip( transformBoxPath, new SoTransform() );
}
}
// This is called when a manipulator is
// about to begin manipulation.
class DragStartCallback extends SoDraggerCB
{
SoMaterial m_material;
public DragStartCallback( SoMaterial mat ) { m_material = mat; }
public void invoke( SoDragger d )
{
m_material.diffuseColor.setValue( new SbColor( 1.0f, 0.2f, 0.2f ) );
}
}
// This is called when a manipulator is
// done manipulating.
class DragFinishCallback extends SoDraggerCB
{
SoMaterial m_material;
public DragFinishCallback( SoMaterial mat ) { m_material = mat; }
public void invoke( SoDragger d )
{
m_material.diffuseColor.setValue( new SbColor( 0.8f, 0.8f, 0.8f ) );
}
}
}

Clip Plane Manipulator

ClipPlaneManip/ClipPlaneManip.cxx.

C++ :

int
main( int argc, char** argv )
{
// Initialize Inventor and Xt
Widget myWindow = SoXt::init( argv[0] );
const char* filename = "../../../../data/models/slotMachine.iv";
if ( argc < 2 )
printf( "Usage : %s <file.iv>\n", argv[0] );
if ( argc >= 2 )
filename = argv[1];
// Read the file
SoSeparator* scene = readFile( filename );
scene->ref();
// Compute the bounding box of the scene graph.
SoGetBoundingBoxAction bboxAction( SbViewportRegion( 100, 100 ) );
bboxAction.apply( scene );
// Inserting the manipulator at the center of the scene graph
// and in the plane YZ.
SoClipPlaneManip* clipPlaneManip = new SoClipPlaneManip;
clipPlaneManip->setValue( bboxAction.getBoundingBox(), SbVec3f( 1, 0, 0 ), 0.1 );
scene->insertChild( clipPlaneManip, 0 );
// Create a viewer
SoXtExaminerViewer* myViewer = new SoXtExaminerViewer( myWindow );
// Attach and show viewer
myViewer->setSceneGraph( scene );
myViewer->setTitle( "File Reader" );
myViewer->show();
// Loop forever
SoXt::show( myWindow );
SoXt::mainLoop();
return 0;
}

C# :

string filename = "$OIVNETHOME/data/models/slotMachine.iv";
string[] args = Environment.GetCommandLineArgs();
if ( args.Length < 2 )
Console.WriteLine( "Usage : {0} <file.iv>\n", Application.ExecutablePath );
if ( args.Length >= 2 )
filename = args[1];
// Read the file
SoSeparator scene = ReadFile( filename );
// Compute the bounding box of the scene graph.
SoGetBoundingBoxAction bboxAction = new SoGetBoundingBoxAction( new SbViewportRegion( 100, 100 ) );
bboxAction.Apply( scene );
// Inserting the manipulator at the center of the scene graph and in the plane YZ.
SoClipPlaneManip clipPlaneManip = new SoClipPlaneManip();
clipPlaneManip.SetValue( bboxAction.GetBoundingBox(), new SbVec3f( 1, 0, 0 ), 0.1f );
scene.InsertChild( clipPlaneManip, 0 );
// Create a viewer
SoWinExaminerViewer myViewer = new SoWinExaminerViewer( this, "", true, SoWinFullViewer.BuildFlags.BUILD_ALL, SoWinViewer.Types.BROWSER );
// attach and show viewer
myViewer.SetSceneGraph( scene );
myViewer.SetTitle( "Clip Plane Manipulator" );
myViewer.Show();

Java :

public void start()
{
super.start();
setLayout( new BorderLayout() );
Panel panel = new Panel( new BorderLayout() );
myViewer = new SwSimpleViewer( SwSimpleViewer.EXAMINER );
String filename = "../../../../data/models/slotMachine.iv";
if ( args.length < 1 )
System.out.println( "Use arg <file.iv>\n" );
if ( args.length >= 1 )
filename = args[0];
// Read the file
SoSeparator scene = readFile( filename );
// Compute the bounding box of the scene graph.
SoGetBoundingBoxAction bboxAction = new SoGetBoundingBoxAction( new SbViewportRegion( ( short )100, ( short )100 ) );
bboxAction.apply( scene );
// Inserting the manipulator at the center of the scene graph and in the plane YZ.
SoClipPlaneManip clipPlaneManip = new SoClipPlaneManip();
clipPlaneManip.setValue( bboxAction.getBoundingBox(), new SbVec3f( 1, 0, 0 ), 0.1f );
scene.insertChild( clipPlaneManip, 0 );
// Create a viewer
myViewer = new SwSimpleViewer( SwSimpleViewer.EXAMINER );
// attach and show viewer
myViewer.setSceneGraph( scene );
panel.add( myViewer );
add( panel );
}