Monday, January 4, 2010

Scene Graph Creation









Scene Graph Creation


The scene graph is created by the constructor for WrapCheckers3D:



public WrapCheckers3D( )
{
// initialization code

GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration( );
Canvas3D canvas3D = new Canvas3D(config);
add("Center", canvas3D);
canvas3D.setFocusable(true); // give focus to the canvas
canvas3D.requestFocus( );

su = new SimpleUniverse(canvas3D);


createSceneGraph( );

initUserPosition( ); // set user's viewpoint
orbitControls(canvas3D); // controls for moving the viewpoint

su.addBranchGraph( sceneBG );
}



The Canvas3D object is initialized with a configuration obtained from getPreferredConfiguration( ); this method queries the hardware for rendering information. Some older Java 3D programs don't bother initializing a GraphicsConfiguration object, using null as the argument to the Canvas3D constructor instead. This is bad programming practice.


canvas3D is given focus so keyboard events will be sent to behaviors in the scene graph. Behaviors are often triggered by key presses and releases, but they may be triggered by timers, frame changes, and events generated by Java 3D internally. There aren't any behaviors in Checkers3D, so it's not necessary to set the focus. I've left these lines in since they're needed in almost every other program we'll consider.


The su SimpleUniverse object creates a standard view branch graph and the VirtualUniverse and Locale nodes of the scene graph. createSceneGraph( ) sets up the lighting, the sky background, the floor, and floating sphere; initUserPosition( ) and orbitControls( ) handle viewer issues. The resulting BranchGroup is added to the scene graph at the end of the method:



private void createSceneGraph( )
{
sceneBG = new BranchGroup( );
bounds = new BoundingSphere(new Point3d(0,0,0), BOUNDSIZE);


lightScene( ); // add the lights
addBackground( ); // add the sky
sceneBG.addChild( new CheckerFloor( ).getBG( ) ); // add floor

floatingSphere( ); // add the floating sphere

sceneBG.compile( ); // fix the scene
} // end of createSceneGraph( )



Various methods add subgraphs to sceneBG to build the content branch graph. sceneBG is compiled once the graph has been finalized to allow Java 3D to optimize it. The optimizations may involve reordering the graph and regrouping and combining nodes. For example, a chain of transformGroup nodes containing different translations may be combined into a single node. Another possibility is to group all the shapes with the same appearance properties together, so they can be rendered more quickly.


bounds is a global BoundingSphere used to specify the influence of environment nodes for lighting, background, and the OrbitBehavior object. The bounding sphere is placed at the center of the scene and affects everything within a BOUNDSIZE units radius. Bounding boxes and polytopes are available in Java 3D.


The scene graph by the end of WrapCheckers3D( ) is shown in Figure 15-3.


The "Floor Branch" node is my invention to hide some details until later. Missing from Figure 15-3 is the view branch part of the scene graph.



Lighting the Scene


One ambient and two directional lights are added to the scene by lightScene( ). An ambient light reaches every corner of the world, illuminating everything equally.



Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
// Set up the ambient light
AmbientLight ambientLightNode = new AmbientLight(white);
ambientLightNode.setInfluencingBounds(bounds);
sceneBG.addChild(ambientLightNode);



The color of the light is set, the ambient source is created along with bounds and added to the scene. The Color3f( ) constructor takes Red/Green/Blue values between 0.0f and 1.0f (1.0f being "full-on").


A directional light mimics a light from a distant source, hitting the surfaces of objects from a specified direction. The main difference from an ambient light is the requirement for a direction vector.



Vector3f light1Direction = new Vector3f(-1.0f, -1.0f, -1.0f);
// left, down, backwards
DirectionalLight light1 = new DirectionalLight(white, light1Direction);
light1.setInfluencingBounds(bounds);
sceneBG.addChild(light1);




Figure 15-3. Partial scene graph for Checkers3D



The direction is the vector between (0, 0, 0) and (-1, -1, -1); the light can be imagined to be multiple parallel lines with that direction, originating at infinity.


Point and spot lights are the other forms of Java 3D lighting. Point lights position the light in space, emitting in all directions. Spot lights are focused point lights, aimed in a particular direction.




The Scene's Background


A background for a scene can be specified as a constant color (as shown here), a static image, or a texture-mapped geometry such as a sphere:



Background back = new Background( );
back.setApplicationBounds( bounds );
back.setColor(0.17f, 0.65f, 0.92f); // sky color
sceneBG.addChild( back );











    No comments: