com.andgate.ikou.render.FloorRender.java Source code

Java tutorial

Introduction

Here is the source code for com.andgate.ikou.render.FloorRender.java

Source

/*
This file is part of Ikou.
Ikou is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
Ikou is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Ikou.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.andgate.ikou.render;

import com.andgate.ikou.model.Floor;
import com.andgate.ikou.model.TilePalette;
import com.andgate.ikou.model.TileSector;
import com.andgate.ikou.model.TileStack;
import com.andgate.ikou.utility.Array2d;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.RenderableProvider;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.Pool;

public class FloorRender implements RenderableProvider, Disposable {
    private static final int SUBSECTOR_SIZE = TileSector.SIZE;
    private SectorMesh[][] sectorMeshes;
    public final Matrix4 floorTransform = new Matrix4();
    private PerspectiveCamera camera;
    private Vector3 position = new Vector3();
    private Vector3 size = new Vector3();
    private float scale = 1.0f;

    public FloorRender(Floor floor) {
        this.camera = null;
        buildMeshes(floor);
        calculateSize();
    }

    public PerspectiveCamera getCamera() {
        return camera;
    }

    public void setCamera(PerspectiveCamera camera) {
        this.camera = camera;
    }

    private void buildMeshes(Floor floor) {
        Array2d<TileSector> sectors = floor.getMasterSector().getSectors();
        TilePalette palette = floor.getPalette();

        int rows = sectors.size;
        sectorMeshes = new SectorMesh[rows][];
        for (int currRow = 0; currRow < rows; currRow++) {
            int columns = sectors.get(currRow).size;
            sectorMeshes[currRow] = new SectorMesh[columns];
            for (int currColumn = 0; currColumn < columns; currColumn++) {
                int offsetX = currColumn * TileSector.SIZE;
                int offsetZ = currRow * TileSector.SIZE;

                SectorMesh sectorMesh = new SectorMesh(floor.getMasterSector(), currRow, currColumn, palette,
                        offsetX, offsetZ);

                sectorMesh.setNeedsRebuild();
                sectorMeshes[currRow][currColumn] = sectorMesh;
            }
        }
    }

    private void calculateSize() {
        size.x = 0;
        size.y = 0;
        size.z = 0;

        for (SectorMesh[] sectorMeshRow : sectorMeshes) {
            for (SectorMesh sectorMesh : sectorMeshRow) {
                Mesh mesh = sectorMesh.getMesh();

                if (mesh != null) {
                    BoundingBox bbox = mesh.calculateBoundingBox();

                    size.x += bbox.getWidth();
                    size.y = Math.max(size.y, bbox.getHeight());
                    size.z += bbox.getDepth();
                }
            }
        }
    }

    public float getWidth() {
        return size.x * scale;
    }

    public float getHeight() {
        return size.y * scale;
    }

    public float getDepth() {
        return size.z * scale;
    }

    public void setPosition(Vector3 position) {
        this.position.set(position);
        applyTransforms();
    }

    public void translate(float x, float y, float z) {
        this.position.add(x, y, z);
        applyTransforms();
    }

    public void centerOnOrigin() {
        translate(getWidth() / -2.0f, 0.0f, getDepth() / -2.0f);
    }

    public void scaleToBoxSize(float length) {
        float floorLength = size.x > size.z ? size.x : size.z;
        scale = length / floorLength;

        applyTransforms();
    }

    private void applyTransforms() {
        floorTransform.idt().translate(position).scl(scale);
    }

    public void resetTransform() {
        floorTransform.idt();

        position.setZero();
        scale = 1.0f;
    }

    private final Vector3 subsectorPosition = new Vector3();

    @Override
    public void getRenderables(Array<Renderable> renderables, Pool<Renderable> pool) {
        for (int i = 0; i < sectorMeshes.length; i++) {
            for (int j = 0; j < sectorMeshes[i].length; j++) {
                Mesh mesh = sectorMeshes[i][j].getMesh();

                if (inFrustum(i, j) && (mesh != null)) {
                    Renderable renderable = pool.obtain();
                    renderable.material = TileStack.TILE_MATERIAL;
                    renderable.meshPartOffset = 0;
                    renderable.meshPartSize = mesh.getNumIndices();
                    renderable.primitiveType = GL20.GL_TRIANGLES;
                    renderable.mesh = mesh;
                    renderables.add(renderable);

                    renderable.worldTransform.set(floorTransform);
                }
            }
        }
    }

    private boolean inFrustum(int sectorRow, int sectorColumn) {
        if (camera == null)
            return true;

        floorTransform.getTranslation(subsectorPosition);
        subsectorPosition.x += sectorColumn * SUBSECTOR_SIZE;
        subsectorPosition.z += sectorRow * SUBSECTOR_SIZE;

        return camera.frustum.sphereInFrustum(subsectorPosition, SUBSECTOR_SIZE * 1.5f);
    }

    @Override
    public void dispose() {
        disposeMeshes();
    }

    public void disposeMeshes() {
        for (SectorMesh[] sectorMeshRow : sectorMeshes) {
            for (SectorMesh sectorMesh : sectorMeshRow) {
                if (sectorMesh != null)
                    sectorMesh.dispose();
            }
        }
    }
}