< Zurück | Inhalt | Weiter >

From PickCollisionTest.java


/*

* This example creates a large hollow box (out of ColorCubes,

* one for each side of the box). Within the box, four Spheres are

* created. Each Sphere has a behavior attached that detects

* collisions with the sides of the box, and the other Spheres.

* When a collision is detected, the trajectory of the Sphere is

* reversed and the color of the Sphere changed. When a collision

* is not detected, the Sphere is advanced along its

* current trajectory.

*/

class PickCollisionTest extends Java3dApplet implements ActionListener

{

private static int m_kWidth = 400; private static int m_kHeight = 400;

private static final int boxSize = 10; public PickCollisionTest()

{

initJava3d();

}


public void actionPerformed( ActionEvent event )

{

}


protected void addCanvas3D( Canvas3D c3d )

{

add( c3d ); doLayout();

}

protected double getScale()

{

return 0.5;

}


//recursively set the user data for objects in the scenegraph tree void recursiveSetUserData( SceneGraphObject root, Object value )

{

root.setUserData( value );


//recursively process group if( root instanceof Group )

{

Group g = (Group) root;


//recurse on child nodes

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


while( enumKids.hasMoreElements() != false ) recursiveSetUserData( (SceneGraphObject)

enumKids.nextElement(), value );

}

}


protected void addCube( BranchGroup bg, double x, double y,

double z, double sx, double sy, double sz, String name,

boolean wireframe )

{

//create four ColorCube objects TransformGroup cubeTg = new TransformGroup(); Transform3D t3d = new Transform3D();

t3d.setTranslation( new Vector3d( x, y, z ) ); t3d.setScale( new Vector3d( sx, sy, sz ) ); cubeTg.setTransform( t3d );

ColorCube cube = new ColorCube( 1.0 );


//we have to make the front face wireframe

//we can't see inside the box! if ( wireframe )

{

Appearance app = new Appearance(); app.setPolygonAttributes(

new PolygonAttributes( PolygonAttributes.POLYGON_LINE,

PolygonAttributes.CULL_NONE, 0 ) ); cube.setAppearance( app );

}


cubeTg.addChild( cube ); recursiveSetUserData( cubeTg, name );


bg.addChild( cubeTg );

}


protected void addSphere( BranchGroup bg, double x,

double y, double z,

Vector3d incVector, String name )

{

Appearance app = new Appearance();


TransformGroup sphereTg = new TransformGroup(); Transform3D t3d = new Transform3D();

t3d.setTranslation( new Vector3d( x, y, z ) ); sphereTg.setTransform( t3d );


sphereTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); sphereTg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);


sphereTg.addChild( new Sphere( 1, app ) ); bg.addChild( sphereTg ); recursiveSetUserData( sphereTg, name );


//create the collision behavior CollisionBehavior collisionBehavior =

new CollisionBehavior( bg, sphereTg, app, new Vector3d( x,y,z ), incVector );

collisionBehavior.setSchedulingBounds( getApplicationBounds() ); bg.addChild( collisionBehavior );

}


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


//create ColorCube objects, one for each side of a cube addCube( objRoot, 0,boxSize,0, boxSize,0.1,boxSize,

"Top", false );

addCube( objRoot, 0,−boxSize,0, boxSize,0.1,boxSize, "Bottom", false );

addCube( objRoot, boxSize,0,0, 0.1,boxSize,boxSize, "Right", false );

addCube( objRoot, −boxSize,0,0, 0.1,boxSize,boxSize, "Left", false );

addCube( objRoot, 0,0,−boxSize, boxSize,boxSize,0.1, "Back", false );

addCube( objRoot, 0,0,boxSize, boxSize,boxSize,0.1, "Front", true );


//create the spheres

addSphere( objRoot, 0,3,4, new Vector3d( 0.1,0.3,0.1),

"Sphere 1" );

addSphere( objRoot, 3,0,−2, new Vector3d( 0.4,0.1,0.2),

"Sphere 2" );

addSphere( objRoot, 0,−3,0, new Vector3d( 0.2,0.2,0.6),

"Sphere 3" );

addSphere( objRoot, −3,0,−4, new Vector3d( 0.1,0.6,0.3),

"Sphere 4" );


return objRoot;

}


public static void main(String[] args)

{

PickCollisionTest pickCollisionTest = new PickCollisionTest();

pickCollisionTest.saveCommandLineArguments( args );


new MainFrame( pickCollisionTest, m_kWidth, m_kHeight );

}

}


/*

* This behavior detects collisions between the branch of a scene,

* and a collision object. The Java 3D 1.2 picking utilities are used

* to implement collision detection. The objects in the scene

* that are collidable should have their user data set. The collision

* object's user data is used to ignore collisions between the object

* and itself.

*

* When a collision is detected the trajectory of the collision object

* is reversed (plus a small random factor) and an Appearance object

* is modified.

*

* When a collision is not detected the collision object is moved

* along its current trajectory and the Appearance color is reset.

*

* Collision checking is run after every frame.

*/

class CollisionBehavior extends Behavior

{

//the wake up condition for the behavior

protected WakeupCondition m_WakeupCondition = null;


//how often we check for a collision

private static final int ELAPSED_FRAME_COUNT = 1;


//the branch that we check for collisions private BranchGroup pickRoot = null;


//the collision object that we are controlling private TransformGroup collisionObject = null;


//the appearance object that we are controlling private Appearance objectAppearance = null;


//cached PickBounds object used for collision detection private PickBounds pickBounds = null;


//cached Material objects that define the collided and

//missed colors

private Material collideMaterial = null; private Material missMaterial = null;


//the current trajectory of the object private Vector3d incrementVector = null;


//the current position of the object private Vector3d positionVector = null;


public CollisionBehavior( BranchGroup pickRoot,

TransformGroup collisionObject, Appearance app,

Vector3d posVector, Vector3d incVector )

{

//save references to the objects this.pickRoot = pickRoot; this.collisionObject = collisionObject;

this.objectAppearance = app;


incrementVector = incVector; positionVector = posVector;


//create the WakeupCriterion for the behavior WakeupCriterion criterionArray[] = new WakeupCriterion[1]; criterionArray[0] =

new WakeupOnElapsedFrames( ELAPSED_FRAME_COUNT ); objectAppearance.setCapability( Appearance.ALLOW_MATERIAL_WRITE );

collisionObject.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE );

collisionObject.setCapability( Node.ALLOW_BOUNDS_READ );


//save the WakeupCriterion for the behavior m_WakeupCondition = new WakeupOr( criterionArray );

}


public void initialize()

{

//apply the initial WakeupCriterion wakeupOn( m_WakeupCondition );


Color3f objColor = new Color3f(1.0f, 0.1f, 0.2f); Color3f black = new Color3f(0.0f, 0.0f, 0.0f);

collideMaterial = new Material(objColor, black, objColor,

black, 80.0f);


objColor = new Color3f(0.0f, 0.1f, 0.8f);

missMaterial = new Material(objColor, black, objColor,

black, 80.0f);


objectAppearance.setMaterial( missMaterial );

}


protected void onCollide()

{

objectAppearance.setMaterial( collideMaterial ); incrementVector.negate();

//add a little randomness

incrementVector.x += (Math.random() − 0.5) / 20.0; incrementVector.y += (Math.random() − 0.5) / 20.0; incrementVector.z += (Math.random() − 0.5) / 20.0;

}


protected void onMiss()

{

objectAppearance.setMaterial( missMaterial );

}


protected void moveCollisionObject()

{

Transform3D t3d = new Transform3D();


positionVector.add (incrementVector ); t3d.setTranslation( positionVector );


collisionObject.setTransform( t3d );

public boolean isCollision( PickResult[] resultArray )

{

if( resultArray == null || resultArray.length == 0 ) return false;


/*

* We use the user data on the nodes to ignore the case

* of the collisionObject having collided with itself!

* The user data also gives us a good mechanism for reporting

* the collisions.

*/

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

{

Object userData = resultArray[n].getObject().getUserData();


if ( userData != null &userData instanceof String )

{

//check that we are not colliding with ourselves... if ( ((String) userData).equals( (String)

collisionObject.getUserData() ) == false )

{

System.out.println( "Collision between: " + collisionObject.getUserData() + " and: " + userData );

return true;

}

}

}

return false;

}


public void processStimulus( java.util.Enumeration criteria )

{

while( criteria.hasMoreElements() )

{

WakeupCriterion wakeUp = (WakeupCriterion) criteria.nextElement();


//every N frames, check for a collision

if( wakeUp instanceof WakeupOnElapsedFrames )

{

//create a PickBounds

PickTool pickTool = new PickTool( pickRoot ); pickTool.setMode( PickTool.BOUNDS );


BoundingSphere bounds = (BoundingSphere) collisionObject.getBounds();

pickBounds = new PickBounds(

new BoundingSphere( new Point3d( positionVector.x,

positionVector.y, positionVector.z ),

bounds.getRadius() ) );

pickTool.setShape( pickBounds, new Point3d( 0,0,0 ) ); PickResult[] resultArray = pickTool.pickAll();


if ( isCollision( resultArray ) ) onCollide();

else onMiss();


moveCollisionObject();

}

//assign the next WakeUpCondition, so we are notified again wakeupOn( m_WakeupCondition );

}


image