org.goko.viewer.jogl.utils.render.gcode.DefaultGCodeProviderRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.goko.viewer.jogl.utils.render.gcode.DefaultGCodeProviderRenderer.java

Source

/*
 *   This file is part of Goko.
 *
 *  Goko 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 3 of the License, or
 *  (at your option) any later version.
 *
 *  Goko 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 Goko.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.goko.viewer.jogl.utils.render.gcode;

import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.media.opengl.GL;
import javax.media.opengl.GL3;
import javax.vecmath.Color4f;
import javax.vecmath.Point3d;

import org.apache.commons.collections.CollectionUtils;
import org.goko.core.common.exception.GkException;
import org.goko.core.gcode.bean.GCodeCommand;
import org.goko.core.gcode.bean.GCodeCommandState;
import org.goko.core.gcode.bean.IGCodeProvider;
import org.goko.core.gcode.bean.execution.IGCodeExecutionToken;
import org.goko.core.gcode.service.IGCodeExecutionListener;
import org.goko.viewer.jogl.service.JoglUtils;
import org.goko.viewer.jogl.shaders.EnumGokoShaderProgram;
import org.goko.viewer.jogl.shaders.ShaderLoader;
import org.goko.viewer.jogl.utils.render.gcode.colorizer.MotionModeGCodeColorizer;
import org.goko.viewer.jogl.utils.render.gcode.geometry.GCodePartitionCodeGenerator;
import org.goko.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer;

import com.jogamp.common.nio.Buffers;

/**
 * Default GCode provider renderer
 * @author PsyKo
 *
 */
public class DefaultGCodeProviderRenderer extends AbstractVboJoglRenderer
        implements IGCodeProviderRenderer, IGCodeExecutionListener {
    /** Command state layout */
    private static final int STATE_LAYOUT = 2;
    /** The GCodeProvider to render */
    private IGCodeProvider gcodeProvider;
    /** The list of vertices */
    private List<Point3d> lstVertices;
    /** The vertices generator */
    GCodePartitionCodeGenerator generator;
    /** TEST : the map of vertices by ID */
    private Map<Integer, Integer[]> mapVerticesPositionByIdCommand;
    /** GCode colorizer */
    private IGCodeColorizer colorizer;
    /** Float buffer for command state */
    private IntBuffer stateBuffer;
    /** The id of the state buffer object*/
    private Integer stateBufferObject;

    /**
     * Constructor
     * @param gcodeProvider the GCodeProvider to render
     */
    public DefaultGCodeProviderRenderer(IGCodeProvider gcodeProvider) {
        super(GL.GL_LINE_STRIP, COLORS | VERTICES);
        this.gcodeProvider = gcodeProvider;
        this.generator = new GCodePartitionCodeGenerator();
        this.colorizer = new MotionModeGCodeColorizer();
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#buildGeometry()
     */
    @Override
    protected void buildGeometry() throws GkException {
        List<GCodeCommand> commands = gcodeProvider.getGCodeCommands();
        ArrayList<Point3d> lstVertices = new ArrayList<Point3d>();
        ArrayList<Color4f> lstColors = new ArrayList<Color4f>();
        mapVerticesPositionByIdCommand = new HashMap<Integer, Integer[]>();
        boolean firstCommand = true;
        for (GCodeCommand command : commands) {
            List<Point3d> lstCmdVertices = generator.generateVertices(command);
            if (CollectionUtils.isNotEmpty(lstCmdVertices)) {
                if (firstCommand) {
                    firstCommand = false;
                } else {
                    lstCmdVertices.remove(0);
                }
                // First index is the position of the first vertices that belong to the command
                // Second index is the number of vertices that belongs to this command
                if (CollectionUtils.isNotEmpty(lstCmdVertices)) {
                    mapVerticesPositionByIdCommand.put(command.getId(),
                            new Integer[] { lstVertices.size(), lstCmdVertices.size() });
                    lstVertices.addAll(lstCmdVertices);
                }
                // Let's generate the colors
                Color4f color = colorizer.getColor(command);
                for (Point3d point3d : lstCmdVertices) {
                    lstColors.add(color);
                }
            }
        }
        setVerticesCount(CollectionUtils.size(lstVertices));
        stateBuffer = IntBuffer.allocate(getVerticesCount());
        stateBuffer.rewind();
        //generateCommandStateBuffer();
        setColorsBuffer(JoglUtils.buildFloatBuffer4f(lstColors));
        setVerticesBuffer(JoglUtils.buildFloatBuffer3d(lstVertices));
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#loadShaderProgram(javax.media.opengl.GL3)
     */
    @Override
    protected int loadShaderProgram(GL3 gl) throws GkException {
        return ShaderLoader.loadShader(gl, EnumGokoShaderProgram.GCODE_SHADER);
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#performUpdateBufferObjects(javax.media.opengl.GL3)
     */
    @Override
    protected void performUpdateBufferObjects(GL3 gl) throws GkException {
        //super.performUpdateBufferObjects(gl);
        stateBuffer.rewind();
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, stateBufferObject);
        gl.glBufferData(GL.GL_ARRAY_BUFFER, getVerticesCount() * Buffers.SIZEOF_FLOAT, stateBuffer,
                GL.GL_DYNAMIC_DRAW);
        setUpdateBuffer(false);
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#initializeAdditionalBufferObjects(javax.media.opengl.GL3)
     */
    @Override
    protected void initializeAdditionalBufferObjects(GL3 gl) throws GkException {
        // Initialize the status buffer object
        if (this.stateBufferObject == null) {
            int[] vbo = new int[1];
            gl.glGenBuffers(1, vbo, 0);
            this.stateBufferObject = vbo[0];
        }
        // Make sure we take everything
        stateBuffer.rewind();
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, stateBufferObject);
        gl.glBufferData(GL.GL_ARRAY_BUFFER, getVerticesCount() * Buffers.SIZEOF_FLOAT, stateBuffer,
                GL.GL_DYNAMIC_DRAW);
        gl.glEnableVertexAttribArray(STATE_LAYOUT);
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#enableAdditionalVertexAttribArray(javax.media.opengl.GL3)
     */
    @Override
    protected void enableAdditionalVertexAttribArray(GL3 gl) throws GkException {
        gl.glEnableVertexAttribArray(STATE_LAYOUT);
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, stateBufferObject);
        gl.glVertexAttribPointer(STATE_LAYOUT, 1, GL3.GL_FLOAT, false, 0, 0);
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#disableAdditionalVertexAttribArray(javax.media.opengl.GL3)
     */
    @Override
    protected void disableAdditionalVertexAttribArray(GL3 gl) throws GkException {
        gl.glDisableVertexAttribArray(STATE_LAYOUT);
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.gcode.IGCodeProviderRenderer#getGCodeProvider()
     */
    @Override
    public IGCodeProvider getGCodeProvider() {
        return gcodeProvider;
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.gcode.IGCodeProviderRenderer#setGCodeProvider(org.goko.core.gcode.bean.IGCodeProvider)
     */
    @Override
    public void setGCodeProvider(IGCodeProvider gcodeProvider) {
        this.gcodeProvider = gcodeProvider;
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.gcode.IGCodeProviderRenderer#setColorizer(org.goko.viewer.jogl.utils.render.gcode.IGCodeColorizer)
     */
    @Override
    public void setColorizer(IGCodeColorizer colorizer) throws GkException {
        this.colorizer = colorizer;
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.utils.render.gcode.IGCodeProviderRenderer#getColorizer()
     */
    @Override
    public IGCodeColorizer getColorizer() throws GkException {
        return colorizer;
    }

    /**
     * @param token
     * @throws GkException
     */
    @Override
    public void onExecutionStart(IGCodeExecutionToken token) throws GkException {
        if (stateBuffer != null) {
            int capacity = stateBuffer.capacity();
            for (int i = 0; i < capacity; i++) {
                stateBuffer.put(i, 0);
            }
            update();
        }
    }

    /**
     * @param token
     * @throws GkException
     */
    @Override
    public void onExecutionCanceled(IGCodeExecutionToken token) throws GkException {
        // TODO Auto-generated method stub

    }

    /**
     * @param token
     * @throws GkException
     */
    @Override
    public void onExecutionPause(IGCodeExecutionToken token) throws GkException {
        // TODO Auto-generated method stub

    }

    /**
     * @param token
     * @throws GkException
     */
    @Override
    public void onExecutionComplete(IGCodeExecutionToken token) throws GkException {
        // TODO Auto-generated method stub

    }

    /**
     * @param token
     * @param idCommand
     * @throws GkException
     */
    @Override
    public void onCommandStateChanged(IGCodeExecutionToken token, Integer idCommand) throws GkException {

        Integer[] verticesIndex = mapVerticesPositionByIdCommand.get(idCommand);
        if (verticesIndex != null) {
            GCodeCommandState state = token.getCommandState(idCommand);
            for (int i = verticesIndex[0]; i < verticesIndex[0] + verticesIndex[1]; i++) {
                stateBuffer.put(i, state.state);
            }
            update();
        }
    }
}