FloorTiles.java

/*
 * Copyright © 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.spacemission;

import javax.microedition.m3g.*;

public class FloorTiles {

    private Mesh floorMesh;

    public FloorTiles(Image2D floorIm, int sz) {
        /*
         * Make sure the size value is divisible by 2, since we'll use size/2
         * later.
         */
        int size = (sz / 2) * 2;
        if (size != sz) {
            System.out.println("Size set to multiple of 2: " + size);
        }

        int numTiles = size * size;
        /*
         * Each tile is a 1-by-1 quadrilateral (quad), so numTiles of them will
         * cover a size-by-size floor.
         */

        // build the floor mesh
        VertexBuffer floorVertBuf = makeGeometry(size, numTiles);

        IndexBuffer floorIdxBuf = new TriangleStripArray(
                makeIndicies(numTiles), makeStripLens(numTiles));

        Appearance floorApp = makeAppearance(floorIm);

        floorMesh = new Mesh(floorVertBuf, floorIdxBuf, floorApp);
    } // end of TiledFloor()

    private VertexBuffer makeGeometry(int size, int numTiles) /*
     * numTiles squares centered at the origin on the XZ plane. Normals aren't
     * required since the floor doesn't reflect light.
     */ {
        // create vertices
        short[] verts = makeVerts(size, numTiles);
        VertexArray va = new VertexArray(verts.length / 3, 3, 2);
        va.set(0, verts.length / 3, verts);

        // create texture coordinates
        short[] tcs = makeTexCoords(numTiles);
        VertexArray texArray = new VertexArray(tcs.length / 2, 2, 2);
        texArray.set(0, tcs.length / 2, tcs);

        VertexBuffer vb = new VertexBuffer();
        vb.setPositions(va, 1.0f, null); // no scale, bias
        vb.setTexCoords(0, texArray, 1.0f, null);

        return vb;
    }

    private short[] makeVerts(int size, int numTiles) {
        short[] verts = new short[12 * numTiles]; // 3 * 4 points for each tile
        int i = 0;
        for (int z = (-size / 2) + 1; z <= size / 2; z++) {
            for (int x = -size / 2; x <= (size / 2) - 1; x++) {
                verts[i] = (short) x;
                verts[i + 1] = 0;
                verts[i + 2] = (short) z;
                verts[i + 3] = (short) (x + 1);
                verts[i + 4] = 0;
                verts[i + 5] = (short) z;
                verts[i + 6] = (short) (x + 1);
                verts[i + 7] = 0;
                verts[i + 8] = (short) (z - 1);
                verts[i + 9] = (short) x;
                verts[i + 10] = 0;
                verts[i + 11] = (short) (z - 1);
                i += 12;
            }
        }
        return verts;
    }

    private short[] makeTexCoords(int numTiles) {
        short[] tcs = new short[8 * numTiles]; // 2 * 4 points for each tile
        for (int i = 0; i < 8 * numTiles; i += 8) { // {0,1, 1,1, 1,0, 0,0}
            tcs[i] = 0;
            tcs[i + 1] = 1; // for each tile
            tcs[i + 2] = 1;
            tcs[i + 3] = 1;
            tcs[i + 4] = 1;
            tcs[i + 5] = 0;
            tcs[i + 6] = 0;
            tcs[i + 7] = 0;
        }
        return tcs;
    }

    private int[] makeIndicies(int numTiles) { // positions for first tile: {1,2,0,3}
        int pos1 = 1;
        int pos2 = 2;
        int pos3 = 0;
        int pos4 = 3;

        int[] idxs = new int[4 * numTiles]; // 4 points for each tile
        for (int i = 0; i < 4 * numTiles; i += 4) {
            idxs[i] = pos1;
            pos1 += 4; // increment the positions by 4
            idxs[i + 1] = pos2;
            pos2 += 4;
            idxs[i + 2] = pos3;
            pos3 += 4;
            idxs[i + 3] = pos4;
            pos4 += 4;
        }
        return idxs;
    }

    private int[] makeStripLens(int numTiles) {
        int[] lens = new int[numTiles];
        for (int i = 0; i < numTiles; i++) {
            lens[i] = 4;
        }
        return lens;
    }

    private Appearance makeAppearance(Image2D floorIm) // No Material, with the texture clamped to each tile
    {
        Appearance app = new Appearance();

        if (floorIm != null) {
            Texture2D tex = new Texture2D(floorIm);
            tex.setFiltering(Texture2D.FILTER_NEAREST,
                             Texture2D.FILTER_NEAREST);
            tex.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
            app.setTexture(0, tex);
        }

        // add perspective correction
        PolygonMode floorPolygonMode = new PolygonMode();
        floorPolygonMode.setPerspectiveCorrectionEnable(true);
        // floorPolygonMode.setCulling(PolygonMode.CULL_NONE); // switch off
        // culling

        app.setPolygonMode(floorPolygonMode);

        return app;
    }

    public Mesh getFloorMesh() {
        return floorMesh;
    }
}