com.github.fauu.helix.core.MapRegionMesh.java Source code

Java tutorial

Introduction

Here is the source code for com.github.fauu.helix.core.MapRegionMesh.java

Source

/*
 * Copyright (C) 2014 Helix Engine Developers (http://github.com/fauu/HelixEngine)
 *
 * This software is licensed under the GNU General Public License
 * (version 3 or later). See the COPYING file in this distribution.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this software. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authored by: Piotr Grabowski <fau999@gmail.com>
 */

package com.github.fauu.helix.core;

import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.math.Matrix3;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;

public class MapRegionMesh extends Mesh {

    public static final int NUM_POSITION_COMPONENTS = 3;
    public static final int NUM_TEXTURE_COMPONENTS = 2;
    public static final int NUM_COLOR_COMPONENTS = 1;
    public static final int NUM_COMPONENTS = 6;

    private boolean ready = false;
    private int[] tileOffsets;
    private GeometrySet geometrySet;
    private TextureAtlas textureAtlas;
    private Tile[] tiles;
    private int numVertices;

    public MapRegionMesh(Tile[] tiles, GeometrySet geometrySet, TextureAtlas textureAtlas) {
        super(true, 1024 * tiles.length, 0,
                new VertexAttribute(VertexAttributes.Usage.Position, NUM_POSITION_COMPONENTS, "a_position"),
                new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, NUM_TEXTURE_COMPONENTS,
                        "a_texCoord0"),
                new VertexAttribute(VertexAttributes.Usage.ColorPacked, 4, "a_color"));

        this.numVertices = 1024 * tiles.length;

        this.geometrySet = geometrySet;
        this.textureAtlas = textureAtlas;
        this.tiles = tiles;

        this.update();
    }

    public void update() {
        ready = false;
        tileOffsets = new int[tiles.length];

        final float[] vertices = new float[numVertices];

        int vertexCount = 0;
        for (int i = 0; i < tiles.length; i++) {
            final Tile tile = tiles[i];
            final Model tileGeometryModel = geometrySet.getGeometry(tile.getGeometryId()).getModel();

            float[] geometryVertices = new float[(NUM_COMPONENTS - NUM_COLOR_COMPONENTS)
                    * tileGeometryModel.meshes.first().getNumVertices()];

            final Texture texture = textureAtlas.getTextures().first();
            final TextureRegion tileTextureRegion = textureAtlas.getRegions().get(tile.getTextureId());

            final Vector2 tileTextureCoords = new Vector2(tileTextureRegion.getU(), tileTextureRegion.getV2());
            final Vector2 tileTextureScaling = new Vector2(
                    (float) tileTextureRegion.getRegionWidth() / texture.getWidth(),
                    (float) tileTextureRegion.getRegionHeight() / texture.getHeight());

            float rotationDegrees = 0;
            switch (tile.getFacing()) {
            case SOUTH:
                rotationDegrees = -90;
                break;
            case WEST:
                rotationDegrees = -180;
                break;
            case NORTH:
                rotationDegrees = 90;
                break;
            case EAST:
                rotationDegrees = 0;
                break;
            default:
            }

            final Matrix3 transformationMatrixUV = new Matrix3().translate(tileTextureCoords)
                    .scale(1 * tileTextureScaling.x, -1 * tileTextureScaling.y).translate(0, -1);

            final Matrix4 transformationMatrix = new Matrix4().translate(
                    new Vector3(0.5f + tile.getPosition().x, tile.getElevation(), 0.5f + tile.getPosition().y))
                    .rotate(new Vector3(0, 1, 0), rotationDegrees);

            // Not sure if copying isn't slower than detransforming the original, but it fixes glitchy
            // edges
            final Mesh tileGeometryMesh = tileGeometryModel.meshes.first().copy(true);

            tileGeometryMesh.transform(transformationMatrix);
            tileGeometryMesh.transformUV(transformationMatrixUV);
            tileGeometryMesh.getVertices(geometryVertices);

            final float[] coloredVertices = new float[NUM_COMPONENTS
                    * tileGeometryModel.meshes.get(0).getNumVertices()];

            final Color tileColor = tile.getColor();

            for (int j = 0, k = 0; j < coloredVertices.length; j++) {
                if ((j + 1) % 6 != 0) {
                    coloredVertices[j] = geometryVertices[k++];
                } else {
                    coloredVertices[j] = tileColor.toFloatBits();
                }
            }

            tileOffsets[i] = vertexCount;

            System.arraycopy(coloredVertices, 0, vertices, vertexCount, coloredVertices.length);

            vertexCount += coloredVertices.length;
        }

        setVertices(vertices, 0, vertexCount);
        ready = true;
    }

    public void updateTileColor(Tile tile) {
        ready = false;

        final Model tileGeometryModel = this.geometrySet.getGeometry(tile.getGeometryId()).getModel();
        final int numVertices = NUM_COMPONENTS * tileGeometryModel.meshes.first().getNumVertices();
        final float[] tileVertices = new float[numVertices];
        Color tileColor;

        if (tile.isHighlighted()) {
            tileColor = new Color(0.5f, 0.5f, 0.5f, 1);
        } else {
            tileColor = tile.getColor();
        }

        getVertices(this.tileOffsets[tile.getNo()], numVertices, tileVertices);

        for (int i = 0; i < numVertices; i++) {
            if ((i + 1) % 6 == 0) {
                tileVertices[i] = tileColor.toFloatBits();
            }
        }

        updateVertices(this.tileOffsets[tile.getNo()], tileVertices);

        ready = true;
    }

    public boolean isReady() {
        return ready;
    }

    public void setReady(boolean ready) {
        this.ready = ready;
    }

}