org.ah.gcode.preview.GCodePreview.java Source code

Java tutorial

Introduction

Here is the source code for org.ah.gcode.preview.GCodePreview.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Creative Sphere Limited.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *    Creative Sphere - initial API and implementation
 *
 *
 *
 *******************************************************************************/
package org.ah.gcode.preview;

import java.util.ArrayList;
import java.util.List;

import org.ah.gcode.preview.gcode.Context;
import org.ah.gcode.preview.gcode.GCodeModel;
import org.ah.gcode.preview.gcode.GCodeParser;
import org.ah.gcode.preview.player.Controller;
import org.ah.gcode.preview.utils.ModelBuilders;
import org.ah.gcode.preview.utils.SceneCameraInputController;
import org.ah.libgdx.components.Console;
import org.ah.libgdx.components.Panel;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.BitmapFontLoader.BitmapFontParameter;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.graphics.g3d.utils.TextureProvider.AssetTextureProvider;
import com.badlogic.gdx.math.Vector3;

/**
 *
 * @author Daniel Sendula
 */
public class GCodePreview extends ApplicationAdapter {

    public static final int SIXTY_FPS_FRAME = 1000 / 60;

    private AssetManager assetManager;
    private AssetTextureProvider textureProvider;

    private PerspectiveCamera camera;

    private BitmapFont font;

    private SpriteBatch spriteBatch;
    private ModelBatch modelBatch;
    private Environment environment;

    private List<ModelInstance> instances = new ArrayList<ModelInstance>();

    private GCodeModel gCodeModel;

    private DirectionalLight directionalLight;

    private OrthographicCamera spriteFontCamera;

    private boolean loadingAssets;
    private boolean parsingGCode;
    private boolean bedCreated;
    boolean preparingMeshes;
    private GCodeParser parser;

    private Console console;

    private Color lightColor;

    private GCodePreviewWindow window;

    private Controller controller;

    private ExitCallback exitCallback;

    private List<String> lines;

    private ModelInstance planeInstance;

    @Override
    public void create() {
        assetManager = new AssetManager();

        BitmapFontParameter bitmapFontParameter = new BitmapFontParameter();
        bitmapFontParameter.flip = true;
        assetManager.load("arial-15.fnt", BitmapFont.class, bitmapFontParameter);
        assetManager.load("bed.png", Texture.class);
        assetManager.load("checked.png", Texture.class);

        assetManager.load("gui/slider-end-left.png", Texture.class);
        assetManager.load("gui/slider-end-right.png", Texture.class);
        assetManager.load("gui/slider-horizontal.png", Texture.class);
        assetManager.load("gui/slider-end-up.png", Texture.class);
        assetManager.load("gui/slider-end-down.png", Texture.class);
        assetManager.load("gui/slider-vertical.png", Texture.class);
        assetManager.load("gui/knob.png", Texture.class);
        prepareButtonImage(assetManager, "gui/ok");
        prepareButtonImage(assetManager, "gui/cancel");
        prepareButtonImage(assetManager, "gui/three-circles");
        prepareButtonImage(assetManager, "gui/media/begin");
        prepareButtonImage(assetManager, "gui/media/end");
        prepareButtonImage(assetManager, "gui/media/play");
        prepareButtonImage(assetManager, "gui/media/pause");
        prepareButtonImage(assetManager, "gui/media/fast-forward");
        prepareButtonImage(assetManager, "gui/media/fast-backward");

        textureProvider = new AssetTextureProvider(assetManager);

        loadingAssets = true;

        Vector3 lightDirection = new Vector3(-0.5f, -0.5f, -1f).nor();
        lightColor = Color.WHITE;
        directionalLight = new DirectionalLight().set(lightColor, lightDirection);

        spriteBatch = new SpriteBatch();
        modelBatch = new ModelBatch();
        spriteFontCamera = new OrthographicCamera();

        environment = new Environment();
        environment.set(new NumberAttribute(NumberAttribute.Number, 1000));

        modelBatch = new ModelBatch();

        environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 1.0f, 1.0f, 0.6f, 1f));
        // environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
        environment.add(directionalLight);

        camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        camera.near = 0.001f;
        camera.far = 600f;

        camera.position.set(0f, 8f, 25f);
        camera.lookAt(0, 0, 0);

        int width = Gdx.graphics.getWidth();
        int height = Gdx.graphics.getHeight();
        window = new GCodePreviewWindow(0, 0, width, height);
        resize(width, height);

        parser = new GCodeParser();
    }

    private void prepareButtonImage(AssetManager assetManager, String image) {
        assetManager.load(image + ".png", Texture.class);
        assetManager.load(image + "-over.png", Texture.class);
        assetManager.load(image + "-selected.png", Texture.class);
    }

    @Override
    public void dispose() {
        assetManager.dispose();
        window.dispose();
    }

    @Override
    public void resize(int width, int height) {
        camera.viewportWidth = width;
        camera.viewportHeight = height;
        spriteFontCamera.setToOrtho(true, width, height);
        window.setSize(width, height);
    }

    public void loadModel() {
        if (lines != null) {
            parser.initParsing(lines);
            lines = null;
            if (gCodeModel != null) {
                gCodeModel.dispose();
            }
            gCodeModel = parser.getModel();
            parsingGCode = true;

        }
    }

    protected void finishedLoading() {
        loadingAssets = false;

        font = assetManager.get("arial-15.fnt");
        window.initialise(textureProvider, font);
        window.layout();
        console = window.getConsole();

        loadModel();
    }

    protected void createBed(float bedWidth, float bedHeight) {
        Texture checkedTexture = textureProvider.load("bed.png");

        Material checkedMaterial = new Material(TextureAttribute.createDiffuse(checkedTexture));
        Material emptyMaterial = new Material();

        ModelBuilder modelBuilder = new ModelBuilder();

        Mesh mesh = ModelBuilders.createRectY2(0f, 0f, 0f, bedWidth, bedHeight, 0);
        modelBuilder.begin();
        modelBuilder.part("1", mesh, GL20.GL_TRIANGLES, checkedMaterial);
        Model planeModel = modelBuilder.end();

        planeInstance = new ModelInstance(planeModel);
        instances.add(planeInstance);

        SceneCameraInputController sceneCameraInputController = new SceneCameraInputController(camera,
                planeInstance);
        controller = new Controller(gCodeModel, window, sceneCameraInputController, exitCallback);
        Gdx.input.setInputProcessor(controller);

        controller.getLeftPanel().setVisible(true);

        Model axisModel = modelBuilder.createXYZCoordinates(10, emptyMaterial,
                Usage.Position | Usage.ColorUnpacked | Usage.Normal);
        ModelInstance axisInstance = new ModelInstance(axisModel);
        instances.add(axisInstance);
    }

    protected void parseGCode() {
        long now = System.currentTimeMillis();
        while (System.currentTimeMillis() - now < SIXTY_FPS_FRAME) {
            if (parser.isFinished()) {

                Material whiteMaterial = new Material(ColorAttribute.createAmbient(1f, 1f, 1f, 1f),
                        new BlendingAttribute(true, 1f));
                Context context = new Context();
                context.material = whiteMaterial;

                gCodeModel.prepareForProcessing(context);
                parsingGCode = false;
                preparingMeshes = true;

                if (!bedCreated) {
                    float bedWidth = 210f;
                    float bedHeight = 150f;
                    if (gCodeModel.getBedWidth() > 0) {
                        bedWidth = gCodeModel.getBedWidth();
                    }
                    if (gCodeModel.getBedHeight() > 0) {
                        bedHeight = gCodeModel.getBedHeight();
                    }
                    createBed(bedWidth, bedHeight);
                    bedCreated = true;
                }
            } else {
                parser.parseNextLine();
                if (!bedCreated && parser.getModel().getBedWidth() > 0) {
                    createBed(parser.getModel().getBedWidth(), parser.getModel().getBedHeight());
                    bedCreated = true;
                }
            }
        }
        Panel playPanel = window.getPlayPanel();
        playPanel.setVisible(true);
        playPanel.refresh();
        playPanel.text("Parsed lines: ", 0);
        playPanel.text(parser.getCurrentLine() + "/" + parser.getLines().size(), 1);
    }

    protected void prepareMesh() {
        Panel playPanel = window.getPlayPanel();

        long now = System.currentTimeMillis();
        while (preparingMeshes && System.currentTimeMillis() - now < SIXTY_FPS_FRAME) {
            if (gCodeModel.isProcessingFinished()) {
                console.println("Total layers: " + gCodeModel.getLayers().size());
                console.println("Total instructions: " + gCodeModel.getTotalInstrctions());
                console.println("Max instrs per layer: " + gCodeModel.getMaxInstructionsPerLayer());
                console.println();

                //                playPanel.setVisible(false);
                playPanel.refresh();
                playPanel.text("Created meshes for all layers", 0);

                if (controller.getLeftPanel().isVisible()) {
                    controller.consoleAtStartup();
                }
                preparingMeshes = false;

                controller.resetView();
                controller.setCurrentLayer(0);
                controller.setTwoDView();
            } else {
                gCodeModel.processNextLayer();
            }
            //            console.println("Processed " + gCodeModel.getCurrentLayerNo() + " meshes");
        }
        if (preparingMeshes) {
            // While still preparing meshes
            controller.setCurrentLayer(gCodeModel.getLayers().size());
            playPanel.setVisible(true);
            playPanel.refresh();
            playPanel.text("Creating meshes for layers", 0);
            playPanel.text(gCodeModel.getCurrentLayerNo() + "/" + gCodeModel.getLayers().size(), 1);
        }
    }

    @Override
    public void render() {
        if (loadingAssets && assetManager.update()) {
            finishedLoading();
        }

        if (loadingAssets) {
        } else {
            if (parsingGCode) {
                parseGCode();
            } else if (preparingMeshes) {
                prepareMesh();
            } else {
            }
        }
        camera.update();
        Vector3 lightDirection = new Vector3(camera.direction).nor();
        directionalLight.set(lightColor, lightDirection);

        // Magic rendering initialisation
        Gdx.gl.glDisable(GL20.GL_CULL_FACE);
        Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
        //        Gdx.gl.glEnable(GL20.GL_BLEND);
        //        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT
                | (Gdx.graphics.getBufferFormat().coverageSampling ? GL20.GL_COVERAGE_BUFFER_BIT_NV : 0));

        Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

        if (instances.size() > 0) {
            modelBatch.begin(camera);
            for (ModelInstance instance : instances) {
                modelBatch.render(instance, environment);
            }

            // gCodeModel.render(modelBatch, environment);
            modelBatch.end();
        }
        if (controller != null) {
            controller.render(camera, environment);
        }

        spriteBatch.begin();
        spriteBatch.setProjectionMatrix(spriteFontCamera.combined);
        spriteBatch.enableBlending();
        window.render(spriteBatch);
        spriteBatch.end();
    }

    public static class NumberAttribute extends IntAttribute {
        public static final String NumberAlias = "number";
        public static final long Number = register(NumberAlias);

        public NumberAttribute(long type, int value) {
            super(type, value);
        }
    }

    public ExitCallback getExitCallback() {
        return exitCallback;
    }

    public void setExitCallback(ExitCallback exitCallback) {
        this.exitCallback = exitCallback;
    }

    public void setLines(List<String> lines) {
        this.lines = lines;
    }

}