Adding Landscape WallsThe landscape walls surround the terrain and are covered with a mountain range image. Calculating the walls' position in space is somewhat simpler if they are added to sceneBG, which permits world coordinates to be used. The walls surround the terrain after it has been rotated and scaled, so lie in the XZ plane, with lengths LAND_LEN (see Figure 27-16). Their y-axis extent is obtained from the minimum and maximum heights for the terrain, scaled to world size. Figure 27-16. Landscape wallsThe following code takes care of this: // Landscape globals private static final double LAND_LEN = 60.0; // length of landscape in world coordinates private static final String WALL_PIC = "models/mountain2Sq.jpg"; private void addWalls( ) { // heights used for the walls, in world coords double minH = minHeight * scaleLen; double maxH = maxHeight * scaleLen; // the eight corner points // back, left Point3d p1 = new Point3d(-LAND_LEN/2.0f, minH, -LAND_LEN/2.0f); Point3d p2 = new Point3d(-LAND_LEN/2.0f, maxH, -LAND_LEN/2.0f); // front, left Point3d p3 = new Point3d(-LAND_LEN/2.0f, minH, LAND_LEN/2.0f); Point3d p4 = new Point3d(-LAND_LEN/2.0f, maxH, LAND_LEN/2.0f); // front, right Point3d p5 = new Point3d(LAND_LEN/2.0f, minH, LAND_LEN/2.0f); Point3d p6 = new Point3d(LAND_LEN/2.0f, maxH, LAND_LEN/2.0f); // back, right Point3d p7 = new Point3d(LAND_LEN/2.0f, minH, -LAND_LEN/2.0f); Point3d p8 = new Point3d(LAND_LEN/2.0f, maxH, -LAND_LEN/2.0f); // load texture; set magnification filter since the image is enlarged TextureLoader loader = new TextureLoader(WALL_PIC, null); Texture2D texture = (Texture2D) loader.getTexture( ); if (texture == null) System.out.println("Cannot load wall image from " + WALL_PIC); else { System.out.println("Loaded wall image: " + WALL_PIC); texture.setMagFilter(Texture2D.BASE_LEVEL_LINEAR); } // left wall sceneBG.addChild( new TexturedPlane(p3, p1, p2, p4, texture)); // front wall sceneBG.addChild( new TexturedPlane(p5, p3, p4, p6, texture)); // right wall sceneBG.addChild( new TexturedPlane(p7, p5, p6, p8, texture)); // back wall sceneBG.addChild( new TexturedPlane(p1, p7, p8, p2, texture)); } // end of addWalls( ) The same image is used for each wall: mountain2Sq.jpg, which is shown in Figure 27-17. It was originally a wide, thin image but resized to form a square suitable for a texture. It's only 7 KB, so it becomes pixilated when viewed up close inside Terra3D. For that reason, magnification filtering is switched on to smooth the image's enlargement. Another way of improving the image quality is to use a more detailed, larger image. Figure 27-18 shows one of the walls in the test1.obj terrain. Figure 27-17. mountain2Sq.jpg: the mountain rangeFigure 27-18. A landscape wall in Terra3DA Wall as a Textured PlaneEach wall is an instance of the TexturedPlane class, which is a simplified descendent of TexturedPlanes in FractalLand3D from Chapter 26. // in addWalls( ) // add the left wall to the scene sceneBG.addChild( new TexturedPlane(p3, p1, p2, p4, texture)); The geometry is simpler since only one QuadArray is created to hold the wall's four corners. No normals are specified since the node's appearance doesn't enable lighting or utilize a Material node. The appearance is represented by the texture, with no lighting effects. The complete TexturedPlane class is shown as Example 27-1. Example 27-1. The TexturedPlane classpublic class TexturedPlane extends Shape3D { private static final int NUM_VERTS = 4; public TexturedPlane(Point3d p1, Point3d p2, Point3d p3, Point3d p4, Texture2D tex) { createGeometry(p1, p2, p3, p4); Appearance app = new Appearance( ); app.setTexture(tex); // set the texture setAppearance(app); } // end of TexturedPlane( ) private void createGeometry(Point3d p1, Point3d p2, Point3d p3, Point3d p4) { QuadArray plane = new QuadArray(NUM_VERTS, GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2 ); // anti-clockwise from bottom left plane.setCoordinate(0, p1); plane.setCoordinate(1, p2); plane.setCoordinate(2, p3); plane.setCoordinate(3, p4); TexCoord2f q = new TexCoord2f( ); q.set(0.0f, 0.0f); plane.setTextureCoordinate(0, 0, q); q.set(1.0f, 0.0f); plane.setTextureCoordinate(0, 1, q); q.set(1.0f, 1.0f); plane.setTextureCoordinate(0, 2, q); q.set(0.0f, 1.0f); plane.setTextureCoordinate(0, 3, q); setGeometry(plane); } // end of createGeometry( ) } // end of TexturedPlane class |