< Zurück | Inhalt | Weiter >

From VrmlPickingTest.java


//This example loads a VRML file, automatically computes

//the view point to view the objects in the file,

//and then mouse picks. For each pick, all the selected components

//of the scene are reported (by their VRML name).

//The VRML scene can be rotated, scaled, and

//translated using the mouse.

public class VrmlPickingTest extends Java3dApplet implements MouseListener

{

PickCanvas pickCanvas = null; public VrmlPickingTest()

{

}


public VrmlPickingTest( String[] args )

{

saveCommandLineArguments( args ); initJava3d();

}


protected void addCanvas3D( Canvas3D c3d )

{

setLayout( new BorderLayout() ); add( "Center", c3d ); doLayout();


if ( m_SceneBranchGroup != null )

{

c3d.addMouseListener( this );

pickCanvas = new PickCanvas( c3d, m_SceneBranchGroup ); pickCanvas.setMode( PickTool.GEOMETRY_INTERSECT_INFO ); pickCanvas.setTolerance( 4.0f );

}

c3d.setCursor( new Cursor( Cursor.HAND_CURSOR ) );

}


public TransformGroup[] getViewTransformGroupArray()

{

TransformGroup[] tgArray = new TransformGroup[1]; tgArray[0] = new TransformGroup();


Transform3D viewTrans = new Transform3D(); Transform3D eyeTrans = new Transform3D();


BoundingSphere sceneBounds = (BoundingSphere) m_SceneBranchGroup.getBounds();


//point the view at the center of the object Point3d center = new Point3d(); sceneBounds.getCenter( center );

double radius = sceneBounds.getRadius(); Vector3d temp = new Vector3d( center ); viewTrans.set( temp );


//pull the eye back far enough to see the whole object double eyeDist = 1.4 * radius /

Math.tan( Math.toRadians( 40 ) / 2.0);

temp.x = 0.0;

temp.y = 0.0; temp.z = eyeDist;

eyeTrans.set( temp ); viewTrans.mul( eyeTrans );


//set the view transform tgArray[0].setTransform( viewTrans );


return tgArray;

}


protected BranchGroup createSceneBranchGroup()

{

BranchGroup objRoot = super.createSceneBranchGroup(); Bounds lightBounds = getApplicationBounds();

AmbientLight ambLight =

new AmbientLight( true, new Color3f( 1.0f, 1.0f, 1.0f) ); ambLight.setInfluencingBounds( lightBounds ); objRoot.addChild( ambLight );


DirectionalLight headLight = new DirectionalLight(); headLight.setInfluencingBounds( lightBounds );


objRoot.addChild( headLight );


TransformGroup mouseGroup = createMouseBehaviorsGroup(); String vrmlFile = null;

try

{

URL codebase = getWorkingDirectory();

vrmlFile = codebase.toExternalForm() + "/VRML/BoxConeSphere.wrl";

}

catch( MalformedURLException mue )

{

}


if ( m_szCommandLineArray != null )

{

switch ( m_szCommandLineArray.length )

{

case 0: break;


case 1:

vrmlFile = m_szCommandLineArray[0]; break;


default:

System.err.println("Usage: VrmlPickingTest [pathname|URL]"); System.exit( −1 );

}

}

BranchGroup sceneRoot = loadVrmlFile( vrmlFile ); if ( sceneRoot != null )

mouseGroup.addChild( sceneRoot );

objRoot.addChild( mouseGroup ); return objRoot;

}


private TransformGroup createMouseBehaviorsGroup()

{

TransformGroup examineGroup = new TransformGroup(); examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);


Bounds behaviorBounds = getApplicationBounds();


MouseRotate mr = new MouseRotate( examineGroup ); mr.setSchedulingBounds( behaviorBounds ); examineGroup.addChild( mr );

MouseTranslate mt = new MouseTranslate( examineGroup ); mt.setSchedulingBounds( behaviorBounds ); examineGroup.addChild( mt );


MouseZoom mz = new MouseZoom( examineGroup ); mz.setSchedulingBounds( behaviorBounds ); examineGroup.addChild( mz );


return examineGroup;

}


private BranchGroup loadVrmlFile( String location )

{

BranchGroup sceneGroup = null; Scene scene = null;

VrmlLoader loader = new VrmlLoader(); try

{

URL loadUrl = new URL(location); try

{

//load the scene

scene = loader.load(new URL(location));

}

catch (Exception e)

{

System.out.println("Exception loading URL:" + e);

}

}

catch (MalformedURLException badUrl)

{

//location may be a path name try

{

//load the scene

scene = loader.load(location);

}

catch (Exception e)

{

System.out.println("Exception loading file from path:" + e);

}

}


if (scene != null)

{

//get the scene group

sceneGroup = scene.getSceneGroup();


sceneGroup.setCapability( BranchGroup.ALLOW_BOUNDS_READ ); sceneGroup.setCapability( BranchGroup.ALLOW_CHILDREN_READ );


Hashtable namedObjects = scene.getNamedObjects(); System.out.println("*** Named Objects in VRML file:

\n" + namedObjects);


//recursively set the user data here so we can find our objects

//when they are picked

java.util.Enumeration enumValues = namedObjects.elements(); java.util.Enumeration enumKeys = namedObjects.keys();


if( enumValues != null )

{

while( enumValues.hasMoreElements() != false )

{

Object value = enumValues.nextElement(); Object key = enumKeys.nextElement();


recursiveSetUserData( value, key );

}

}

}


return sceneGroup;

}


//Method to recursively set the user data for objects

//in the scenegraph tree we also set the capabilities

//on Shape3D and Morph objects required by the PickTool void recursiveSetUserData( Object value, Object key )

{

if( value instanceof SceneGraphObject != false )

{

//set the user data for the item SceneGraphObject sg = (SceneGraphObject) value; sg.setUserData( key );


//recursively process group if( sg instanceof Group )

{

Group g = (Group) sg;


//recurse on child nodes

java.util.Enumeration enumKids = g.getAllChildren();


while( enumKids.hasMoreElements() != false ) recursiveSetUserData( enumKids.nextElement(), key );

}

else if ( sg instanceof Shape3D || sg instanceof Morph )

{

PickTool.setCapabilities( (Node) sg, PickTool.INTERSECT_FULL );

}

}

}


public void mouseClicked(MouseEvent e)

{

System.out.println("*** MouseClick ***");


pickCanvas.setShapeLocation( e );

PickResult[] results = pickCanvas.pickAllSorted();


if( results != null )

{

for (int n = 0; n <results.length; n++ )

{

PickResult pickResult = results[n];


System.out.println(

"Sorted PickResult " + n + ": " + pickResult ); Node actualNode = pickResult.getObject();

if( actualNode.getUserData() != null )

{

System.out.println(

"Sorted Object " + n + ": " + actualNode.getUserData() );

}

}

}

PickResult pickResult = pickCanvas.pickClosest(); if( pickResult != null )

{

System.out.println( "Closest PickResult: " + pickResult ); Node actualNode = pickResult.getObject();

if( actualNode.getUserData() != null )

{

System.out.println(

"Closest Object: " + actualNode.getUserData() );

}

}


}

public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public static void main( String[] args )

{

VrmlPickingTest pickingTest = new VrmlPickingTest( args );


new MainFrame( pickingTest, 400, 400 );

}

}


image


The VrmlPickingTest example sets up a simple AWT application or applet, loads a VRML file into it and when an AWT MouseEvent is generated calculates PickResults for each intersection between the ray perpendicular to the Canvas and the loaded VRML model.


The initJava3D method initializes Java 3D—it creates a VirtualUniverse from scratch, and does not use the SimpleUniverse utility class. By overriding Java3dApplet methods, users of the class can customize the functionality and configuration of the VirtualUniverse created by the base class. In this example, the addCanvas3D method is overridden to assign a Canvas3D to a AWT Container, the getViewTransformGroupArray method creates an array of TransformGroups to be used on the view side of the scenegraph, while the createSceneBranchGroup method returns a BranchGroup containing all the scenegraph elements for the scene side of the scenegraph. The remaining methods are utility methods defined by the VrmlPickingTest class to implement the example functionality.


The addCanvas3D method sets up the AWT UI elements; specifically it assigns a BorderLayout algorithm and adds a Canvas3D to the center area of the AWT Component. Additionally the addCanvas3D method adds a MouseListener instance of this to the Canvas3D so that the VrmlPickingTest class will receive a callback from AWT when mouse events occur. A PickCanvas is created for the Canvas3D using the PickTool.GEOMETRY_INTERSECT_INFO intersection mode to calculate PickResults. The tolerance for picking is set to 4.0. Finally, the cursor for the Canvas3D is set

to the standard AWT hand−cursor icon.


The createSceneBranchGroup method loads the VRML file using the VRML 97 VrmlLoader class. After having been loaded from a URL or File, the named objects in the VRML file are iterated and the User Data field is set to the VRML name of the object. Assigning the VRML name to the User Data will make it easy to identify which object in the scene has been picked with the mouse—we can just grab the picked Node and examine its user data field.


The PickResult calculation is performed within the AWT mouse callback method mouseClicked. When a mouse click occurs AWT will invoke the method passing in a MouseEvent object that describes the position of the mouse and button states when the click took place. We merely have to call pickCanvas.setShapeLocation to assign the MouseEvent to the PickCanvas and then call pickCanvas.pickAllSorted for the PickCanvas to return an array of PickResults with all the intersections sorted from furthest to nearest.