CHAPTER 9

Setting geometry appearances

9.1 Introduction

9.2 Appearance

9.3 ColoringAttributes

9.4 LineAttributes

9.5 Material

9.6 PointAttributes

9.7 PolygonAttributes

9.8 RenderingAttributes

9.9 TexCoordGeneration

9.10 TextureAttributes

9.11 Texture

9.12 TransparencyAttributes

9.13 Summary

The Java 3D Appearance class enables you to set rendering attributes for the geometric primitives in your scene—at startup, during scenegraph creation, or dynamically at runtime. After reading this chapter, you should be able to dynamically modify the appearance of the geometry within your scenegraph.

9.1 Introduction

Java 3D contains a host of classes to specify the rendering attributes for geometric primitives, such as color, texture, back-face removal, and so on. Java 3D defines “has-a” relationships between the classes that control overall rendering appearance. For example, an Appearance has a Material class, a PolygonAttributes class, a RenderingAttributes class, and so on. This is one of the best-designed areas of Java 3D; with a little experience you can quickly learn to navigate the various classes that, when combined, specify object appearance. Compared with learning the plethora of separate OpenGL methods to specify appearance, the OO nature of the Java 3D design pays dividends.

An instance of an Appearance object is associated with each Shape3D geometric object in the scenegraph. The Appearance object defines rendering state information that must be applied to the rendering pipeline before the raw geometry within the Shape3D is rendered.

It is useful to think of the Java 3D renderer traversing through the defined scenegraph; when it encounters TransformGroups, it applies matrix transformations; when it encounters a Shape3D Node, it applies the Shape3D’s Appearance state—all before executing the Shape3D object to generate native graphics API calls.

What follows is an overview of the NodeComponent-derived classes that define a Java 3D rendering state for a Shape3D object. Emphasis is placed on areas of potential confusion or typical problems. Consult the detailed Sun API reference for a method-by-method summary of the classes. I have prefaced each section with a table listing the capability bits that control access to the specific feature being discussed. The tables include references to OpenGL functions where appropriate and useful.

One of the lengthier examples of the book accompanies this chapter: AppearanceTest (illustrated in figure 9.1) allows you to dynamically modify most of the Appearance attributes on a simple scene. I encourage you to examine the code for the example and run it as you work through this chapter—most of the sections will be significantly clarified by this interactive example.

Figure 9.1

Figure 9.1 The AppearanceTest example application allows Appearance settings to be modified at runtime

9.2 Appearance

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Appearance

The Appearance class contains member variables that together define an appearance state for a Shape3D object. A Shape3D object basically contains Geometry and Appearance. The Appearance class itself does not define any of the properties that control Shape3D appearance, but instead packages Appearance subcomponents, such as PolygonAttributes, RenderingAttributes, and so on.

The Appearance class controls access to its member variables through the familiar, but rigorous, process of setting capability bits. That is, the application developer must specify which Appearance member variables will be modified after the Appearance is attached to a live scenegraph. A live scenegraph is one that has either been compiled or has been rendered.

The capability bits that control access to the member variables of the Appearance class are:

Preface the listed items with ALLOW_ and add _READ or _WRITE for read or write access respectively. For example, to allow read/write access to the Material and PolygonAttributes member variables, you would put the following in your code:

Appearance app = new Appearance();
app.setCapability( ALLOW_MATERIAL_READ );
app.setCapability( ALLOW_MATERIAL_WRITE );
app.setCapability( ALLOW_POLYGON_ATTRIBUTES_READ );
app.setCapability( ALLOW_ POLYGON_ATTRIBUTES_WRITE );
NOTE     
 
 
Four separate calls must be made to the setCapability method—it is not possible to OR together the various capabilities. ORing together capability bits will lead to very unpredictable behavior.

Public accessor methods to access the member variable are defined as:

app.setMaterial( new Material() );
app.setPolygonAttributes( new PolygonAttributes() );

PolygonAttributes polyAttribs = app.getPolygonAttributes();
Material material = app.getMaterial();

9.3 ColoringAttributes

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.ColoringAttributes
Table 9.1 Capability bits for the ColoringAttributes class
COLOR
SHADE_MODE
OpenGL Reference: glColor

The ColoringAttributes within a Shape3D’s Appearance are used to control the color of a Shape3D if a Material has not also been assigned to the Appearance. If a Material has been assigned, the ColoringAttributes are ignored and the more complex color and lighting information within the Material class are used instead. See table 9.1.

The colors of any vertices within the Shape3D that have per-vertex colors applied are unchanged by the ColoringAttributes.

The next example, from AppearanceTest.java, creates a standard Box and then replaces the LEFT face with a new face created with new geometry and per-vertex colors. When a ColoringAttributes object is assigned to the Appearance for the Box it will set the color for the five original faces but will not effect the LEFT face which has per-vertex colors assigned, as illustrated in figure 9.2.

Figure 9.2

Figure 9.2 A Box primitive with an applied ColoringAttribute. The LEFT face has been removed and replaced with a QuadArray that includes per-vertex colors that are unaffected by the ColoringAttributes

int nScale = 50;

Box box = new Box( nScale,nScale,nScale,
                   Primitive.GENERATE_NORMALS |
                   Primitive.GENERATE_TEXTURE_COORDS,
                   m_Appearance);
                   
Shape3D frontFace = box.getShape( Box.LEFT );

//create a new LEFT face so we can assign per-vertex colors
GeometryArray geometry =
 new QuadArray( 4, GeometryArray.COORDINATES |
                   GeometryArray.NORMALS |
                   GeometryArray.COLOR_4 |
                   GeometryArray.TEXTURE_COORDINATE_2 );
                   
nScale = 40;

final float[] verts =
{
 // new LEFT face
 -1.0f * nScale, -1.0f * nScale,  1.0f * nScale,
 -1.0f * nScale,  1.0f * nScale,  1.0f * nScale,
 -1.0f * nScale,  1.0f * nScale, -1.0f * nScale,
 -1.0f * nScale, -1.0f * nScale, -1.0f * nScale
};

final float[] colors =
{
 // left face
 1,0,0,0,
 0,1,0,0.2f,
 0,0,1,0.8f,
 0,0,0,1,
};

float[] tcoords =
{
 // texture coordinates for LEFT face
 1, 0,
 1, 1,
 0, 1,
 0, 0
};

Vector3f normalVector = new Vector3f(-1.0f,  0.0f,  0.0f);

geometry.setColors( 0, colors, 0, 4 );

for( int n = 0; n < 4; n++ )
 geometry.setNormal( n, normalVector );
 
geometry.setTextureCoordinates( 0, tcoords, 0, 4 );
geometry.setCoordinates( 0, verts );

9.4 LineAttributes

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.LineAttributes
Table 9.2 Capability bits for the LineAttributes class
ANTIALIASING
PATTERN
WIDTH
OpenGL Reference: glLineStipple, glLineWidth

The LineAttributes class controls the style of lines used to draw the edges of surfaces. See table 9.2. The available styles are:

To see the effect of the LineAttributes class, the Appearance must be set to render in LINE (wire frame) mode:

Appearance app = new Appearance();
PolygonAttributes polyAttribs = new PolygonAttributes( PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0 );
app.setPolygonAttributes(polyAttribs );

See section 9.7.1 for more detail on PolygonAttributes. Figures 9.3–9.6 show examples rendered using various LineAttribute styles.

Figure 9.3

Figure 9.3 Rendering in LINE mode with a null LineAttributes

Figure 9.4

Figure 9.4 Rendering with a LineAttributes of width 10 without antialiasing

Figure 9.5

Figure 9.5 Rendering with a LineAttributes of width 10 with antialiasing

Figure 9.6

Figure 9.6 Rendering with a LineAttributes of width 2 with a Dash Dot pattern

The lines rendered in LINE mode are effected by color, lighting, and texture applied to surfaces.

9.5 Material

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Material
Table 9.3 Capability bits for the Material class
COMPONENT
OpenGL Reference: glColorMaterial, glMaterial

The Material class specifies surface rendering characteristics (table 9.3) using the following parameters:

The effects of the various colors specified within the Material are described in detail in the context of lighting in chapter 10. Figure 9.7 shows a cube rendered with an applied Material, and per-vertex colors on four vertices of the cube.

Figure 9.7

Figure 9.7 Appearance with an applied Material with Ambient, Diffuse, Emissive, and Specular colors. Lighting calculations determine the shade of each surface

9.6 PointAttributes

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.PointAttributes
Table 9.4 Capability bits for PointAttributes class
ANTIALIASING
SIZE
OpenGL Reference: glPointSize, GL_POINT_SMOOTH

The PointAttributes class specifies rendering information for rendered points (table 9.4). PointAttributes encapsulates two appearance properties:

If antialiasing is enabled, points are rendered as circular; if antialiasing is disabled, points are rendered as square (size pixels by size pixels) as shown in figures 9.8 and 9.9.

Figure 9.8

Figure 9.8 An array of colored points of size 8 pixels with antialiasing

Figure 9.9

Figure 9.9 The same as in figure 9.8 but without antialiasing set in the PointAttributes

NOTE     
 
The time taken to render a point (at least without hardware acceleration) is proportional to the size of the point in pixels.

Note that a single point, when antialiased, approximates a sphere, in that it is never possible to view the point “edge-on” as a disc. When points are rendered without antialiasing, the point approximates a cube with each front face always perpendicular to the viewer. Figures 9.10 and 9.11 illustrate.

Figure 9.10

Figure 9.10 When rotated, antialiased points appear as spheres

Figure 9.11

Figure 9.11 When rotated, nonantialiased points appear as squares aligned with the viewer

The figures are taken from the PointTest.java example. The example defines the points to be rendered, as well as Appearances, as follows:

//create a BranchGroup containing an nNumPoints x nNumPoints
//array of points
//the size of the points is set to nPointSize and antialiasing
//is set to bAliased
private BranchGroup createPoints( final int nPointSize, final int
  nNumPoints, boolean bAliased )
{
 BranchGroup bg = new BranchGroup();
 
 //create a Text3D label describing the points
 String szText = new String();
 szText += ( nNumPoints + "X, Size:" + nPointSize + ", aliased: "
  + bAliased );
  
 Font3D f3d = new Font3D( new Font( "SansSerif", Font.PLAIN, 1), new
  FontExtrusion() );
 Text3D label3D = new Text3D( f3d, szText, new Point3f(-5,0,0) );
 Shape3D sh = new Shape3D( label3D );
 bg.addChild( sh );
 
 //create the PointArray used to hold the geometry for the points
 PointArray pointArray = new PointArray( nNumPoints * nNumPoints,
  GeometryArray.COORDINATES | GeometryArray.COLOR_3 );
  
 //populate the PointArray that we will be rendering
 int nPoint = 0;
 final double factor = 1.0 / nNumPoints;
 
 for( int n = 0; n < nNumPoints; n++ )
 {
  for( int i = 0; i < nNumPoints; i++ )
  {
   Point3f point = new Point3f( n - nNumPoints/2,
                                i - nNumPoints/2, 0.0f );
   pointArray.setCoordinate( nPoint, point );
   pointArray.setColor( nPoint++,
                        new Color3f( 0.5f, (float) (n * factor),
                        (float) (i * factor) ) );
  }
 }
 
 //create the Appearance for the points
 Appearance pointApp = new Appearance();
 
 //enlarge the points and set antialiasing
 pointApp.setPointAttributes( new PointAttributes
  ( nPointSize, bAliased ) );
  
 //create a Shape3D for the PointArray and assign the appearance
 Shape3D pointShape = new Shape3D( pointArray, pointApp );
 
 //add the Shape3D to the BranchGroup and return
 bg.addChild( pointShape );
 return bg;
}

9.7 PolygonAttributes

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.PolygonAttributes
Table 9.5 Capability bits for the PolygonAttributes class
CULL_FACE
MODE
NORMAL_FLIP
OFFSET
OpenGL Reference: glCullFace, glFrontFace, glPolygonMode

The PolygonAttributes class encapsulates properties for how polygons are rendered (table 9.5). Polygon rendering is controlled by the following properties:

For example, to allow write access to the CULL_FACE property, use the following:

PolygonAttributes polyAttribs = new PolygonAttributes();
polyAttribs.setCapability(PolygonAttributes.ALLOW_CULL_FACE_WRITE );
Table 9.6 Cull face parameters
CULL_BACK
CULL_FRONT
CULL_NONE

Cull face parameters (table 9.6) can be implemented as follows:

polyAttribs.setCullFace( PolygonAttributes.CULL_BACK );
Table 9.7 Mode parameters
POLYGON_FILL
POLYGON_LINE
POLYGON_POINT

Polygon fill-mode parameters are shown in table 9.7. For example, to set line-only (wire frame) mode, use the following:

polyAttribs.setPolygonMode( PolygonAttributes.POLYGON_LINE );

Figures 9.12 through 9.15 illustrate how normal vector flipping can influence both the lighting calculations, (compare the shading of the horizontal faces in figure 9.12 with figure 9.13), and surface culling (figure 9.14, 9.15).

Figure 9.12

Figure 9.12 CULL_NONE, NORMAL_FLIP = false

Figure 9.13

Figure 9.13 CULL_NONE, NORMAL_FLIP = true

Figure 9.14

Figure 9.14 CULL_FRONT, NORMAL_FLIP = false

Figure 9.15

Figure 9.15 CULL_FRONT, NORMAL_FLIP = true

9.8 RenderingAttributes

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.RenderingAttributes
Table 9.8 Capability bits for the RenderingAttributes class
ALPHA_TEST_FUNCTION
ALLOW_ALPHA_TEST_VALUE
ALLOW_DEPTH_ENABLE
OpenGL Reference: glAlphaFunc

The RenderingAttributes class allows pixels within the final rendered scene to be included or excluded based on the pixel Alpha (transparency) value (table 9.8).

Assuming an Alpha test value of A, the test conditions listed in table 9.9 and shown in figure 9.16 are available.

Figure 9.16

Figure 9.16 Using RenderingAttributes to control the portions of a QuadArray that are rendered. Vertex 0 has transparency 0.0, vertex 1 has transparency 0.2, vertex 2 has transparency 0.8, and vertex 3 has transparency 1.0. In all cases the Alpha test value was set to 0.5
Table 9.9 Alpha test modes
Alpha test function Meaning
ALWAYS Always render pixel regardless of A
EQUAL Render pixel if pixel transparency = A
GREATER Render pixel if pixel transparency > A
GREATER_OR_EQUAL Render pixel if pixel transparency >= A
LESS Render pixel if pixel transparency < A
LESS_OR_EQUAL Render pixel if pixel transparency <= A
NEVER Never render pixel regardless of A
NOT_EQUAL Render pixel if pixel transparency != A

The interpolation of transparency values across primitives (quads or triangles) can sometimes be surprising. Figure 9.17 illustrates what happens to a QuadArray when it is rotated. In this case vertexes 0 and 1 have a transparency of 0.0, and vertexes 1 and 2 have a transparency of 1.0.

Figure 9.17

Figure 9.17 The lower two vertices have transparency 0.0, while the upper two vertices have transparency 1.0. The Alpha test value is 0.5 and Alpha test function is LESS. Note that, as the QuadArray rotates, the transparency interpolation changes as a function of the rotation and an apparent spike appears in the middle of the quad

9.9 TexCoordGeneration

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.TexCoordGeneration
Table 9.10 Capability bits for the TexCoordGeneration class
ENABLE
FORMAT
MODE
PLANE
OpenGL Reference: glTexGen

Java 3D’s texture capabilities (table 9.10) are discussed in detail in chapter 14.

9.10 TextureAttributes

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.TextureAttributes
Table 9.11 Capability bits for the TextureAttributes class
BLEND_COLOR
MODE
TRANSFORM
OpenGL Reference: glTexParameter

Java 3D’s texture capabilities (table 9.11) are discussed in detail in chapter 14.

9.11 Texture

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Texture
Table 9.12 Capability bits for the Texture class
BOUNDARY_COLOR
ENABLE
FILTER
IMAGE
MIPMAP_MODE
OpenGL Reference: glTexImage2D.

Java 3D’s texture capabilities (table 9.12) are discussed in detail in chapter 14.

9.12 TransparencyAttributes

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.TransparencyAttributes
Table 9.13 Capability bits for the TransparencyAttributes class
MODE
VALUE
OpenGL Reference: glBlendFunc

The TransparencyAttributes class allows the transparency of objects to be specified. Transparency is set using an Alpha value (table 9.13). Alpha values range from 0.0, representing complete opacity, to 1.0, representing complete transparency. Like color, transparency can either be set on a per-vertex basis or, by using the TransparencyAttributes class, for an entire Shape3D. Per-vertex transparency (set using COLOR_4 per-vertex colors) takes precedence over the transparency value specified in the Shape3D’s TransparencyAttributes. The examples to follow will help to illustrate this.

Transparency should be used with care, because, as the OpenGL reference indicates, it is a blending operation between pixels that have their source geometry located at different positions within the scene.

Using transparency slows rendering considerably because the renderer must track the transparency of every pixel in the frame. Without transparency the color of a pixel in the frame is dictated by the color of the geometry closest to the viewer. All other geometry that would be mapped into the frame pixel location can be discarded since it is occluded by the geometry closest to the viewer. If some of the elements in the scenegraph are transparent, however, the renderer must perform a sequence of complex blending operations between the colors generated for a single pixel in the frame.

Figure 9.18

Figure 9.18 Five Sphere primitives with varying transparency, from left to right 100%, 70%, 50%, 30%, and 10%. All of the Spheres have the same color (black)

Here is what the Microsoft/Silicon Graphics OpenGL reference says about using transparency: “Transparency is best implemented using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) with primitives sorted from farthest to nearest. Note that this transparency calculation does not require the presence of alpha bitplanes in the frame buffer. You can also use glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) for rendering antialiased points and lines in arbitrary order.” The key phrase in the description is, “with primitives sorted from farthest to nearest.” This is where the problems with using transparency in Java 3D occur. Because transparency is a Shape3D object attribute, Java 3D users naturally assume that they merely have to set the object or vertex transparency and Java 3D will take care of everything else. Sadly, this is not the case, as Java 3D provides very little support for sorting the primitives “from farthest to nearest.” This should be changing however, as Java 3D 1.3 will implement depth-sorted transparency—as demonstrated as a Sun presentation at the JavaOne 2001 conference.

Traditional 3D rendering techniques rely on the Z-buffer to ensure objects nearer to the viewer are rendered on top of objects further away.

The Z-buffer is essentially an array of depth values, one element in the array for each pixel in the frame. As the scene is rendered, the Z-buffer is updated with the distance of the source location for each pixel from the viewer. The Color buffer tracks the color of the closest source location for each pixel in the frame, as shown in the following sequences:

In this way, when all the geometry in the scene has been prerendered, the Z-buffer contains the depth values for each pixel to the nearest geometry and the Color buffer contains the color for each pixel. When transparency is used, however, the color of a pixel cannot be solely determined from the color of the closest geometry; instead, a complex blend of the colors of all geometry gets mapped to the pixel location. In general, the blending will only be calculated correctly if the geometry is rendered from back to front, which is of course view-dependent.

The problem therefore becomes one of sorting geometry from front to back before rendering takes place. For general scenes this is extremely difficult, especially for scenes that are composed of overlapping or interpenetrating objects. Such objects will have to be decomposed into nonpenetrating subsections before rendering.

Without sorting, you will only get reasonable results if most of your objects are opaque and you have only a few, nonoverlapping, transparent surfaces. The Java 3D rendering order is as follows:

  1. Opaque objects
  2. Ordered objects (OrderedGroups)
  3. Transparent objects

Within the opaque and transparent groups no sorting is performed. Therefore, transparent objects will overlap opaque or ordered objects in front of them, whereas, because transparent objects are not depth-sorted, there are no guarantees that transparent objects will be rendered correctly.

Figures 9.19 through 9.29 illustrate some of the potential rendering problems. The scene for the following figures was composed of a single Box primitive with one face (LEFT) removed. The LEFT face was replaced with a new, slightly smaller face that included per-vertex colors (COLOR_4). The code used to replace the LEFT face follows:

//create a Box with Normal vectors and texture coordinates
Box box = new Box(nScale,nScale,nScale,
           Primitive.GENERATE_NORMALS |
           Primitive.GENERATE_TEXTURE_COORDS, m_Appearance );
           
Shape3D frontFace = box.getShape( Box.LEFT );

//create a new left face so we can assign per-vertex colors
GeometryArray geometry = new QuadArray( 4,  GeometryArray.COORDINATES |
               GeometryArray.NORMALS |
               GeometryArray.COLOR_4 |
               GeometryArray.TEXTURE_COORDINATE_2 );
               
nScale = 40;

//define the geometry for the left face
final float[] verts =
{
  -1.0f * nScale, -1.0f * nScale,  1.0f * nScale,
  -1.0f * nScale,  1.0f * nScale,  1.0f * nScale,
  -1.0f * nScale,  1.0f * nScale, -1.0f * nScale,
  -1.0f * nScale, -1.0f * nScale, -1.0f * nScale
};

//define the colors for the left face. Note we are using RGBA
//colors and include per-vertex transparency
final float[] colors =
 {
 1,0,0,0,
 0,1,0,0.2f,
  0,0,1,0.8f,
  0,0,0,1,
};

//define the texture coordinates for the left face
float[] tcoords =
{
 1, 0,
 1, 1,
 0, 1,
 0, 0
};

//define the normal vector for the new left face
Vector3f normalVector = new Vector3f(-1.0f,  0.0f,  0.0f);

//assign the colors to the QuadArray
geometry.setColors( 0, colors, 0, 4 );

//assign the normal vector for each vertex in the QuadArray
for( int n = 0; n < 4; n++ )
 geometry.setNormal( n, normalVector );
 
//assign the texture coordinates for each vertex in the QuadArray
geometry.setTextureCoordinates( 0, tcoords, 0, 4 );

//finally, assign the vertices themselves into the QuadArray
geometry.setCoordinates( 0, verts );
NOTE     
 
All rendering was performed with PolygonAttributes.CULL_NONE; so all the faces of the Box were rendered.

9.12.1 A warning about transparency

Consider carefully what you are trying to achieve if you choose to use transparency as an Appearance attribute in your scene. It is very difficult to know exactly what will be rendered by Java 3D in either NICEST or SCREEN_DOOR mode, and without some form of application-specific sorting algorithm, which must be carried out potentially on every frame, problems will probably occur.

The issues with transparency really do not reside at the Java3D level, but Java 3D has not done a good job of insulating the Java 3D developer from the underlying issues in the OpenGL/DirectX implementation. I am hopeful that Sun can address many of these issues in Java 3D 1.3.

Figure 9.19

Figure 9.19 Coloring = null, Material = null, Transparency = null

Figure 9.20

Figure 9.20 Coloring = green, Material = null, Transparency = null. Note that the QuadArray with per-vertex colors is unaffected

Figure 9.21

Figure 9.21 Coloring = null, Ambient: white Diffuse: white Emissive: blue, Transparency = null. Lighting is now active and affects the QuadArray with per-vertex colors

Figure 9.22

Figure 9.22 Coloring = null, Material = null. Transparency = 0—NICEST. Here we have set up transparency for both the Box (100% opaque) and the QuadArray (per-vertex transparency). Even though the QuadArray should be visible at the front of the Box, it is being rendered behind the Box. This would be a case that could be solved using a simple sorting algorithm because the centroid of the Box is behind the centroid of the QuadArray and hence it should be rendered before the QuadArray

Figure 9.23

Figure 9.23 Coloring = null, Material = null. Transparency = 0—SCREEN_DOOR. Here, when we switch to SCREEN_DOOR transparency, the rendering order problem disappears

Figure 9.24

Figure 9.24 Coloring = null, Material = null. Transparency = 0.5—NICEST. When the Box is semitransparent, the problem with rendering order is not apparent because you can see the QuadArray through the Box

Figure 9.25

Figure 9.25 Coloring = null, Material = null. Transparency = 0.5—SCREEN_DOOR. Using stippling to simulate transparency is not as realistic as using true color blending

Figure 9.26

Figure 9.26 Coloring = null, Material = null. Transparency = 0.8—NICEST. We have increased the transparency of the Box and rotated it so that the QuadArray is now at the rear of the Box. No problems apparent here

Figure 9.27

Figure 9.27 Coloring = null, Material = null. Transparency = 0.8—SCREEN_DOOR. We have increased the transparency of the Box and rotated it so that the QuadArray is now at the rear of the Box. Using SCREEN_DOOR transparency, the QuadArray has now disappeared

Figure 9.28

Figure 9.28 Coloring = null, Ambient: white, Diffuse: white, Emissive: blue, Transparency = 0.5—NICEST. The scene renders correctly—but continuously renders, cycling over the back faces and then redrawing the front faces

Figure 9.29

Figure 9.29 Coloring = null, Ambient: white, Diffuse: white, Emissive: blue, Transparency = 0.5—SCREEN_DOOR. No problems apparent here

9.13 Summary

Java 3D provides you with a rich set of capabilities for controlling the appearance of your geometry. By combining aspects of the Appearance class, such as materials, transparency, textures, or rendering attributes, you can achieve visually effective scenes with very little programming.

The high-level object-oriented API allows you to easily navigate through the dozens of appearance capabilities and is a real productivity improvement over a lower-level API such as OpenGL. In some areas (for example, transparency), however, it can be important to understand what is going on under the covers, as Java 3D does a poor job at insulating you from the peculiarities of the underlying implementation or providing adequate documentation. If you require additional information I strongly recommend a good 3D graphics text as well as an OpenGL/DirectX reference.

[previous]  |  [main]  |  [next]