< Zurück | Inhalt | Weiter >

From ObjectSizeBehavior.java


class ObjectSizeBehavior extends Behavior

{

//the wake up condition for the behavior

protected WakeupCondition m_WakeupCondition = null;


//the GeometryArray for the Shape3D that we are querying protected GeometryArray m_GeometryArray = null;


//cache some information on the model to save reallocation protected float[] m_CoordinateArray = null;


protected BoundingBox m_BoundingBox = null; protected Point3d m_Point = null;;


public ObjectSizeBehavior( GeometryArray geomArray )

{

//save the GeometryArray that we are modifying m_GeometryArray = geomArray;


//set the capability bits that the behavior requires m_GeometryArray.setCapability(

GeometryArray.ALLOW_COORDINATE_READ ); m_GeometryArray.setCapability(

GeometryArray.ALLOW_COUNT_READ );


//allocate an array for the coordinates m_CoordinateArray =

new float[ 3 * m_GeometryArray.getVertexCount() ];


//create the BoundingBox used to calculate the size of the object m_BoundingBox = new BoundingBox();


//create a temporary point m_Point = new Point3d();


//create the WakeupCriterion for the behavior

WakeupCriterion criterionArray[] = new WakeupCriterion[1]; criterionArray[0] = new WakeupOnElapsedFrames( 20 );


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

}


public void initialize()

{

//apply the initial WakeupCriterion

wakeupOn( m_WakeupCondition );

}


public void processStimulus( java.util.Enumeration criteria )

{

while( criteria.hasMoreElements() )

{

WakeupCriterion wakeUp =

(WakeupCriterion) criteria.nextElement();


//every N frames, recalculate the bounds for the points

//in the GeometryArray

if( wakeUp instanceof WakeupOnElapsedFrames )

{

//get all the coordinates m_GeometryArray.getCoordinates( 0, m_CoordinateArray );


//clear the old BoundingBox m_BoundingBox.setLower( 0,0,0 );

m_BoundingBox.setUpper( 0,0,0 );


//loop over every vertex and combine with the BoundingBox for( int n = 0; n <m_CoordinateArray.length; n+=3 )

{

m_Point.x = m_CoordinateArray[n]; m_Point.y = m_CoordinateArray[n+1]; m_Point.z = m_CoordinateArray[n+2];


m_BoundingBox.combine( m_Point );

}


System.out.println( "BoundingBox: " + m_BoundingBox );

}

}


//assign the next WakeUpCondition, so we are notified again

wakeupOn( m_WakeupCondition );

}

}


image


To use the behavior one could write:


Sphere sphere = new Sphere( 3, Primitive.GENERATE_NORMALS | Primitive.GENERATE_TEXTURE_COORDS,


m_SizeBehavior = new ObjectSizeBehavior( (GeometryArray) sphere.getShape().getGeometry() ); m_SizeBehavior.setSchedulingBounds( getApplicationBounds() );

objRoot.addChild( m_SizeBehavior );


This code snippet creates the behavior and passes the geometry for a Sphere to the constructor, sets the scheduling bounds for the behavior and adds it to the scenegraph. Do not forget to add the behavior to the scenegraph, or it will not get scheduled.


Output from the behavior is simply:


Bounding

box:

Lower=−5.048

−5.044

−5.069

Upper=5.040

5.060

5.069

Bounding

box:

Lower=−5.048

−5.044

−5.069

Upper=5.040

5.060

5.069

Bounding

box:

Lower=−5.048

−5.044

−5.069

Upper=5.040

5.060

5.069


The behavior verifies the size of the geometry for the Shape3D every 20 frames. Note that the behavior follows the general anatomy of a behavior as was described in section 11.3.


When writing a behavior you should be very aware of the computational cost of the processing within the processStimulus method and how often the behavior is likely to be invoked. The ObjectSizeBehavior’s processStimulus method is called once every 20 frames, so any processing that is performed is going to have a fairly big impact on application performance. Whenever possible, avoid creating Objects (using the new operator) within the processStimulus method if it is going to be invoked frequently. Any Objects created by the behavior using the new operator and not assigned to a member variable will have to be garbage−collected. Not only is creating objects a relatively costly operation, but garbage collection can cause your application to noticeably pause during rendering.

For example, instead of creating a new BoundingBox, which would have had size 0, a single

BoundingBox object was resized using:


m_BoundingBox.setLower( 0,0,0 );

m_BoundingBox.setUpper( 0,0,0 );


With Java 3D in general, you should avoid burning (allocate, followed by garbage−collect) Objects as much as possible, and minimize the work that the garbage collector has to perform.