Scenery CreationWrapMaze3D carries out two main tasks: the creation of scene objects (e.g., the floor, the maze, lighting, background) and the initialization of the viewpoint (e.g., its position, orientation, and geometries linked to the viewpoint). createSceneGraph( ) builds the scene: void createSceneGraph( ) { sceneBG = new BranchGroup( ); bounds = new BoundingSphere(new Point3d(0,0,0), BOUNDSIZE); lightScene( ); // add the lights addBackground( ); // ade sky // add the textured floor TexturedFloor floor = new TexturedFloor( ); sceneBG.addChild( floor.getBG( ) ); sceneBG.addChild( mazeMan.getMaze( ) ); // add 3D maze, using MazeManager sceneBG.addChild( camera2TG ); // add second camera sceneBG.compile( ); // fix the scene } // end of createScene( ) lightScene( ) is similar to the lighting code in previous chapters in that it switches on two downward facing lights. However, no ambient light is created, causing the maze's internal walls to be cast into darkness. Making a BackgroundWrapMaze3D has two versions of addBackground( ) to choose from, both of which lay a texture over the inside face of a Sphere. The first version makes the Sphere a child of a Background node: private void addBackground( ) // add a geometric background using a Background node { System.out.println("Loading sky texture: " + SKY_TEX); TextureLoader tex = new TextureLoader(SKY_TEX, null); Sphere sphere = new Sphere(1.0f, Sphere.GENERATE_NORMALS | Sphere.GENERATE_NORMALS_INWARD | Sphere.GENERATE_TEXTURE_COORDS, 4); // default = 15 Appearance backApp = sphere.getAppearance( ); backApp.setTexture( tex.getTexture( ) ); BranchGroup backBG = new BranchGroup( ); backBG.addChild(sphere); Background bg = new Background( ); bg.setApplicationBounds(bounds); bg.setGeometry(backBG); sceneBG.addChild(bg); } A useful way of thinking about a background shape is that it surrounds the scene. This means the user is located inside the background shape and will always see the background shape behind (beyond) the other objects in the scene. This is true even though the Sphere's radius is set to be 1.0f in addBackground( ); the value isn't utilized when the shape is used as a background. The Sphere is set to create inward normal vectors, which will force the texture to appear on its inside facesthe ones visible within the scene. A normal vector for the surface of a polygon is perpendicular to that surface, usually pointing from the interior of the polygon to the outside. The side of the polygon that faces into the object's interior is called the back (or inward) face, and the outward side is the front face. The number of divisions, which controls the number of surfaces that make up the sphere, is reduced from 15 (the default) to 4. The number of surfaces is equal to the square of the number of divisions. This reduction makes little difference to the quality of the background but greatly reduces the cost of generating the sphere.
Unfortunately, some bugs are connected with geometric Backgrounds in the current version of Java 3D (1.3.1). Some (older) graphics cards find it hard to display them. The problems manifest themselves as the background not being rendered at all (i.e., the background is left completely black) or parts of it being rendered inconsistently or being clipped. An alternative is to render an inward facing sphere without using Background: private void addBackground( ) { System.out.println("Loading sky texture: " + SKY_TEX); TextureLoader tex = new TextureLoader(SKY_TEX, null); // create an appearance and assign the texture Appearance app = new Appearance( ); app.setTexture( tex.getTexture( ) ); Sphere sphere = new Sphere(100.0f, // radius to edge of scene Sphere.GENERATE_NORMALS_INWARD | Sphere.GENERATE_TEXTURE_COORDS, 4, app); sceneBG.addChild( sphere ); } The sphere is made as large as the intended radius of the scene and is added to the scene directly. |