The Colored Tiles
ColouredTiles class extends
Shape3D and defines the geometry and appearance of tiles with the same color. The geometry uses a Java 3D
QuadArray to represent the tiles as a series of quadrilaterals (quads). The constructor is
QuadArray(int vertexCount, int vertexFormat);
The vertex format is an ORed collection of
static integers, which specify the different aspects of the quad to be initialized later, such as its coordinates, color, and normals. In
QuadArray plane is created using this line of code:
plane = new QuadArray(coords.size( ), GeometryArray.COORDINATES | GeometryArray.COLOR_3 );
size( ) method returns the number of coordinates in the supplied
ArrayList. The coordinate and color data is supplied in
int numPoints = coords.size( ); Point3f points = new Point3f[numPoints]; coords.toArray( points ); // ArrayList->array plane.setCoordinates(0, points); Color3f cols = new Color3f[numPoints]; for(int i=0; i < numPoints; i++) cols[i] = col; plane.setColors(0, cols);
The order in which a quad's coordinates are specified is significant. The front of a polygon is the face where the vertices form a counterclockwise loop. Knowing front from back is important for lighting and hidden face culling, and by default, only the front face of a polygon will be visible in a scene. In this application, the tiles are oriented so their fronts are facing upward along the y-axis.
It's necessary to ensure that the points of each quad from a convex, planar polygon, or rendering may be compromised. However, each quad in the coordinates array doesn't need to be connected or adjacent to the other quads, which is the case for these tiles.
Since a quad's geometry doesn't include normals information, a
Material node component can't be used to specify the quad's color when lit. I could use a
ColoringAttributes, but a third alternative is to set the color in the geometry, as done here (
plane.setColors(0, cols);). This color will be constant, unaffected by the scene lighting.
Once finalized, the
Shape3D's geometry is set with:
The shape's appearance is handled by
createAppearance( ), which uses a Java 3D
PolygonAttribute component to switch off the culling of the back face.
PolygonAttribute can be employed to render polygons in point or line form (i.e., as wire frames), and to flip the normals of back facing shapes:
Appearance app = new Appearance( ); PolygonAttributes pa = new PolygonAttributes( ); pa.setCullFace(PolygonAttributes.CULL_NONE); app.setPolygonAttributes(pa);
Once the appearance has been fully specified, it's fixed in the shape with
The Floor's Axis Labels
The floor's axis labels are generated with the
labelAxes( ) and
makeText( ) methods in
labelAxes( ) uses two loops to create labels along the x and z. Each label is constructed by
makeText( ) and then added to the floor's
BranchGroup (see Figure 15-5):
floorBG.addChild( makeText(pt,""+i) );
makeText( ) uses the
Text2D utility class to create a 2D string of a specified color, font, point size, and font style:
Text2D message = new Text2D(text, white, "SansSerif", 36, Font.BOLD); // 36 point bold Sans Serif
Text2D object is a
Shape3D object with a quad geometry (a rectangle), and appearance given by a texture map (image) of the string, placed on the front face. By default, the back face is culled; if the user moves behind an axis label, the object becomes invisible.
The point size is converted to virtual-world units by dividing by 256. Generally, it's a bad idea to use too large a point size in the
Text2D( ) constructor since the text may be rendered incorrectly. Instead, a
TransformGroup should be placed above the shape and used to scale it to the necessary size.
The positioning of each label is done by a
TransformGroup above the shape:
TransformGroup tg = new TransformGroup( ); Transform3D t3d = new Transform3D( ); t3d.setTranslation(vertex); // the position for the label tg.setTransform(t3d); tg.addChild(message);
setTranslation( ) only affects the position of the shape. The
tg TransformGroup is added to the floor scene graph.