Tutorial 5 - 3D Shapes and Texturing

In this tutorial we'll move on to real 3d objects. We'll also touch on 2 dimensional texturing using texture coordiantes. Essentially we're extending tutorial 4 but we'll add a new class "Cube" which is based on our Square.

Cube is essentially the same as Square with a few differences. First off we have considerably more geometry.

Cube.java

    QuadArray array = new QuadArray(24,QuadArray.COORDINATES | 
                                       QuadArray.TEXTURE_COORDINATE_2);
        
    // side 1
    array.setCoordinate(0,new Point3d(-1,-1,1));
    array.setCoordinate(1,new Point3d(1,-1,1));
    array.setCoordinate(2,new Point3d(1,1,1));
    array.setCoordinate(3,new Point3d(-1,1,1));
    array.setTextureCoordinate(0,0,new TexCoord2f(0.0f,0.0f));
    array.setTextureCoordinate(0,1,new TexCoord2f(1.0f,0.0f));
    array.setTextureCoordinate(0,2,new TexCoord2f(1.0f,1.0f));
    array.setTextureCoordinate(0,3,new TexCoord2f(0.0f,1.0f));
        
    // side 2
    array.setCoordinate(4,new Point3d(-1,-1,-1));
    array.setCoordinate(5,new Point3d(1,-1,-1));
    array.setCoordinate(6,new Point3d(1,1,-1));
    array.setCoordinate(7,new Point3d(-1,1,-1));
    array.setTextureCoordinate(0,4,new TexCoord2f(0.0f,0.0f));
    array.setTextureCoordinate(0,5,new TexCoord2f(1.0f,0.0f));
    array.setTextureCoordinate(0,6,new TexCoord2f(1.0f,1.0f));
    array.setTextureCoordinate(0,7,new TexCoord2f(0.0f,1.0f));
        
    // side 3
    array.setCoordinate(8,new Point3d(-1,-1,-1));
    array.setCoordinate(9,new Point3d(-1,-1,1));
    array.setCoordinate(10,new Point3d(-1,1,1));
    array.setCoordinate(11,new Point3d(-1,1,-1));
    array.setTextureCoordinate(0,8,new TexCoord2f(0.0f,0.0f));
    array.setTextureCoordinate(0,9,new TexCoord2f(1.0f,0.0f));
    array.setTextureCoordinate(0,10,new TexCoord2f(1.0f,1.0f));
    array.setTextureCoordinate(0,11,new TexCoord2f(0.0f,1.0f));
        
    // side 4
    array.setCoordinate(12,new Point3d(1,-1,-1));
    array.setCoordinate(13,new Point3d(1,-1,1));
    array.setCoordinate(14,new Point3d(1,1,1));
    array.setCoordinate(15,new Point3d(1,1,-1));
    array.setTextureCoordinate(0,12,new TexCoord2f(0.0f,0.0f));
    array.setTextureCoordinate(0,13,new TexCoord2f(1.0f,0.0f));
    array.setTextureCoordinate(0,14,new TexCoord2f(1.0f,1.0f));
    array.setTextureCoordinate(0,15,new TexCoord2f(0.0f,1.0f));
        
    // top
    array.setCoordinate(16,new Point3d(-1,1,-1));
    array.setCoordinate(17,new Point3d(1,1,-1));
    array.setCoordinate(18,new Point3d(1,1,1));
    array.setCoordinate(19,new Point3d(-1,1,1));
    array.setTextureCoordinate(0,16,new TexCoord2f(0.0f,0.0f));
    array.setTextureCoordinate(0,17,new TexCoord2f(1.0f,0.0f));
    array.setTextureCoordinate(0,18,new TexCoord2f(1.0f,1.0f));
    array.setTextureCoordinate(0,19,new TexCoord2f(0.0f,1.0f));
        
    // bottom
    array.setCoordinate(20,new Point3d(-1,-1,-1));
    array.setCoordinate(21,new Point3d(1,-1,-1));
    array.setCoordinate(22,new Point3d(1,-1,1));
    array.setCoordinate(23,new Point3d(-1,-1,1));
    array.setTextureCoordinate(0,20,new TexCoord2f(0.0f,0.0f));
    array.setTextureCoordinate(0,21,new TexCoord2f(1.0f,0.0f));
    array.setTextureCoordinate(0,22,new TexCoord2f(1.0f,1.0f));
    array.setTextureCoordinate(0,23,new TexCoord2f(0.0f,1.0f));
As you can see we build up points or vertices for all the sides of our cube. The quad array definition has been modified to support 24 points, instead of 4. This is the same as with the square, just more points.

The quad array has also been updated to support texture coordinates (TEXTURE_COORDINATE_2). To define how the texture will be mapped on to the surfaces we supply "texture coordinates" for each vertex of the cube. Texture coordinates map from the vertex to the position on the 2 dimensional bitmap or texture. Texture coordinates are generally referred to as (u,v) and in most cases range from 0 to 1. (0,0) is considered the bottom left of the texture image and (1,1) the top right. Hence (0.5,0.5) would be the center of the image.

So, in our case we simply map each corner of each side of the cube to a corner of the texture image. The only thing we have left to do define is what texture we will actually use.

   // we'll add some texturing to this appearance
   Texture texture = new TextureLoader(ClassLoader.getSystemResource("images/logo.jpg"),"RGB",null).getTexture();
   app.setTexture(texture);
   
   // we also need to modulate the texture to allow changes in the surface
   // to effect the texture aswell
   TextureAttributes textureAttributes = new TextureAttributes();
   textureAttributes.setTextureMode(TextureAttributes.MODULATE);
   app.setTextureAttributes(textureAttributes);
Here we've updated the appearance node to define the texture. The first two lines create a texture object from an image. The image is loaded via the class loader, and we use the TextureLoader utility to actually build the texture object. The "RGB" is the format of the texture to be create, in this case Red-Green-Blue.

The second section of the code defines how the texture applied to the surface will be mixed with the normal colour of the surface. Later when we consider lighting we will see why this is so important. For now, using modulation (TextureAttributes.MODULATE) is the standard and most useful setting.

Our cube should now be complete, all we have to do is modify our scene to add it instead of the square.

Display3D.java

    // add the square to the view
    scene.addChild(new Cube());
This final addition to the Display3D constructor puts out new cube into the scene. Finally we have a 3d object being displayed in a Java3D world.

Get the source code
Back to the tutorials page