As you have discovered, the applet produces the above message for most run-time errors. To debug these situations you need to gain access to the debugging capabilities provided by BlueJ. Rather than run as an applet, you will instantiate the object from inside BlueJ, as follows:
1. instantiate the object using the right mouse menu and selecting New
2. invoke the init method using the right mouse menu
3. if your process crashes, use the Java3D error messages to determine the problem
+ you can also place breakpoints in your code and step through, but this seems rather fragile in Bluej
Hopefully this will make your problem much more obvious. Try it now after creating a problem in one of your programs (or solving an existing one).
Adding lights to your Java3D scene really makes it look different. The Material appearance component specifies the color of shapes when lights are shining on them. Lighting is enabled if the geometry for the shape has normals, the Appearance has a Material, and the Material enables lighting. There are several steps involved in doing this:
1. Lights are enabled in a Material node and added to an Appearance node.
Appearance app = new Appearance(); Material material = new Material(); material.setLightingEnable(true); app.setMaterial(material);
2. Lights are defined in a Group.
Group lightGroup = setupLights(); // call a function to specify lights objRoot.addChild(lightGroup);
3. The function setupLights() defines an ambient light and a directional light shining along the -Z axis, with their InfluencingBounds
Group setupLights() { Color3f red = new Color3f(1.0f,0.0f,0.0f); Color3f black = new Color3f(0.0f,0.0f,0.0f); Color3f white = new Color3f(1.0f,1.0f,1.0f); Group group = new Group(); // set up the BoundingSphere for all the lights BoundingSphere bounds = new BoundingSphere(new Point3d(), 100.0); // Set up the ambient light AmbientLight lightAmbient = new AmbientLight(white); lightAmbient.setInfluencingBounds(bounds); group.addChild(lightAmbient); // Set up the directional light Vector3f lightDirection1 = new Vector3f( 0.0f, 0.0f, -1.0f); DirectionalLight lightDirectional1 = new DirectionalLight(red, lightDirection1); lightDirectional1.setInfluencingBounds(bounds); group.addChild(lightDirectional1); return group; }
The color produced by lighting is a combination of the color/properties of the object and the color/properties of the light. The components of Material control the color contributed by the shape to four different kinds of lighting: ambient, emissive, diffuse and specular. There are parameters for specifying the characteristics of each of these. Look at pages 120 - 125 for a description of these light models. Various combinations can be used to model the appearance of real world materials. See the chart at the bottom of page 125.
Copy, compile and run the code ~cs475/java3d/LitSphereApp.java. Look at the code and determine why the sphere looks as it does. Since no color is specified in the Material node, the defaults are in effect.
To see a more complicated example where the Material parameters interact with the Lighting parameters, copy, compile and run ~cs475/java3d/MaterialApp.java. Look at the code and see that the function createMatAppear is called with varying parameters for each of the sphere constructors.
Add two directional lights of different colors to your Temple code. Are all the conditions for lighting met?
Texture files must have dimensions that are powers of 2. You can use xv to examine the characteristics of texture files or to save them to a proper dimension. The sky file bg.jpg is not used as a texture, but rather as a background. Its dimensions are 700x700 so it can not successfully be used as a texture unless it is resiaced.
I was able to use two textures on my model; the method is rather clumsy but it works. I duplicated the DefineAppearance method as DefineAppearance2, opening a different .jpg file. I duplicated the createNGCreaseShape method as createNGCreaseShape2. In the first I indicated the first seven of the quadrilaterals in the indices and the texIndices and called DefineAppearance(). In the second I indicated the remaining seven of the quadrilaterals in the indices and the texIndices and called DefineAppearance2(). It's kludgy but it works; obviously it could be re-written with a single method with parameters to indicate which set of quadrilaterals to use.
In the next session, we will do modeling with the QuadArray rather than the IndexedQuadArray and explore whether specifying textures is easier with the non-indexed specification of the vertices.
As repeated above, I was able to use multiple textures with my kludgy code. I redefined part of my model with the non-indexed form of QuadArray to see if it was easier. Here is the code segment. Note that I just indexed into the pts vector rather than repeating the Point3f for each of the vertices.
TexCoord2f[] texCoords = {new TexCoord2f (0.0f, 0.0f), new TexCoord2f (1.0f, 0.0f), new TexCoord2f (1.0f, 1.0f), new TexCoord2f (0.0f, 1.0f)}; QuadArray qafront = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2); Point3f pts0[] = new Point3f[4]; pts0[0] = pts[0]; pts0[1] = pts[1]; pts0[2] = pts[9]; pts0[3] = pts[8]; qafront.setCoordinates(0,pts0); qafront.setTextureCoordinates(0,0,texCoords); QuadArray qaright= new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2); Point3f pts1[] = new Point3f[4]; pts1[0] = pts[1]; pts1[1] = pts[2]; pts1[2] = pts[10]; pts1[3] = pts[9]; qaright.setCoordinates(0,pts1); qaright.setTextureCoordinates(0,0,texCoords); // A Shape3D may have multiple geometries, but only one appearance Shape3D building = new Shape3D(); building.addGeometry(qafront); building.addGeometry(qaright); building.setAppearance(DefineAppearance()); return building;
As the comment states, a Shape3D may hold multiple geometries but only one appearance. Since an appearance can have only one texture, there seems to be no way around having multiple Shape3D's in order to use multiple textures.
Modify your Building program to use more than one texture.
We will work with more complicated models in the next session.
The example program ~cs475/java3d/AppearanceExplorer permits you to explore many aspects of appearance in Java3D. Start it up now by cd'ing to ~cs475/java3d and typing java AppearanceExplorer. Click through all of the tabs and examine the various parameter settings and their results. Note that various object geometries can be loaded. The source for this program is a good resource for example code. Revisit it now to explore the various settings for materials. Note that when materials are enabled, the color defined by a ColoringAttribute no longer applies.
The example program ~cs475/java3d/EnvironmentExplorer permits you to explore many characteristics of lights in Java3D. Start it up now by cd'ing to ~cs475/java3d and typing javaEnvironmentExplorer. Click through all of the tabs and examine the various parameter settings for the different types of lights and their results.
Email the source code for your modifed Temple, with lights, to wenner@bucknell.edu. Please include the name of both members of your team. Do this by 20 December.
Email the source code for your textured U-shaped building, using two textures, to wenner@bucknell.edu. Do this by 20 December.