Cube with face normals

Now, let's add a light to the scene and render the cube with it. To do this, we also need to define normal vectors for each face of the cube, which are used in the shader calculations.

If you derive Cube from the one in Chapter 3, Cardboard Box, you may already have this code:

    public static final float[] CUBE_NORMALS_FACES = new float[] {
            // Front face
            0.0f, 0.0f, 1.0f,
            // Right face    
            1.0f, 0.0f, 0.0f,
            // Back face
            0.0f, 0.0f, -1.0f,
            // Left face
            -1.0f, 0.0f, 0.0f,
            // Top face
            0.0f, 1.0f, 0.0f,
            // Bottom face
            0.0f, -1.0f, 0.0f,
    };

Now, add a buffers for the normals, like we have for colors and vertices, and allocate them:

    
public static FloatBuffer normalBuffer;
    ...

    public static void allocateBuffers(){
        ...
        
normalBuffer = allocateFloatBuffer( cubeFacesToArray(CUBE_NORMALS_FACES, 3) );
    }

We're going to add a lighting option argument to createMaterial and implement it using VertexColorLightingMaterial if it is set to true:

    public Cube createMaterial(boolean lighting){
        if(lighting){
            VertexColorLightingMaterial mat = new VertexColorLightingMaterial();
            mat.setBuffers(vertexBuffer, colorBuffer, normalBuffer, 36);
            material = mat;
        } else {
            VertexColorMaterial mat = new VertexColorMaterial();
            mat.setBuffers(vertexBuffer, colorBuffer, numIndices);
            material = mat;
        }
        return this;
    }

Of course, the VertexColorLightingMaterial class hasn't been written yet. That's coming up soon. However, first we should create a Light component that can also be added to illuminate the scene.

We will refactor the Cube() constructor method with two variations. When no arguments are given, the Cube does not create any Material. When a Boolean lighting argument is given, that gets passed to createMaterial in order to choose the material:

    public Cube(){
        super();
        allocateBuffers();
    }
    
    public Cube(boolean lighting){
        super();
        allocateBuffers();
        createMaterial(lighting);
    }

We'll remind you later, but don't forget to modify the call to new Cube(true) in MainActivity to pass the lighting option.

Note that we're creating the material in the constructor out of convenience. There is nothing to stop us from just adding a setMaterial() method to RenderObject or making the material variable public. In fact, as the number of object and material types increases, this becomes the only sane way to proceed. This is a drawback of our simplified Material system, which expects a different class per material type.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset