org.goko.viewer.jogl.service.JoglViewerServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.goko.viewer.jogl.service.JoglViewerServiceImpl.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.service;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;

import javax.media.opengl.GL;
import javax.media.opengl.GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.vecmath.Color3f;
import javax.vecmath.Color4f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.goko.core.common.exception.GkException;
import org.goko.core.common.measure.quantity.Length;
import org.goko.core.common.measure.units.Unit;
import org.goko.core.config.GokoPreference;
import org.goko.core.controller.IContinuousJogService;
import org.goko.core.controller.ICoordinateSystemAdapter;
import org.goko.core.controller.IFourAxisControllerAdapter;
import org.goko.core.controller.IThreeAxisControllerAdapter;
import org.goko.core.controller.ThreeToFourAxisAdapterWrapper;
import org.goko.core.gcode.bean.BoundingTuple6b;
import org.goko.core.gcode.bean.IGCodeProvider;
import org.goko.core.gcode.bean.commands.EnumCoordinateSystem;
import org.goko.core.gcode.service.IGCodeExecutionMonitorService;
import org.goko.core.log.GkLog;
import org.goko.core.workspace.service.GCodeProviderEvent;
import org.goko.core.workspace.service.GCodeProviderEvent.GCodeProviderEventType;
import org.goko.core.workspace.service.IWorkspaceListener;
import org.goko.core.workspace.service.IWorkspaceService;
import org.goko.viewer.jogl.GokoJoglCanvas;
import org.goko.viewer.jogl.preferences.JoglViewerPreference;
import org.goko.viewer.jogl.utils.render.GridRenderer;
import org.goko.viewer.jogl.utils.render.ToolRenderer;
import org.goko.viewer.jogl.utils.render.coordinate.CoordinateSystemSetRenderer;
import org.goko.viewer.jogl.utils.render.coordinate.FourAxisRenderer;
import org.goko.viewer.jogl.utils.render.coordinate.measurement.ArrowRenderer;
import org.goko.viewer.jogl.utils.render.gcode.BoundsRenderer;
import org.goko.viewer.jogl.utils.render.gcode.DefaultGCodeProviderRenderer;
import org.goko.viewer.jogl.utils.render.gcode.IGCodeProviderRenderer;
import org.goko.viewer.jogl.utils.render.gcode.RotaryAxisAdapter;
import org.goko.viewer.jogl.utils.render.text.TextRenderer;

import com.jogamp.opengl.util.PMVMatrix;

/**
 * Jogl implementation of the viewer service
 *
 * @author PsyKo
 *
 */
public class JoglViewerServiceImpl extends JoglSceneManager
        implements IJoglViewerService, IWorkspaceListener, IPropertyChangeListener {
    /** LOG */
    private static final GkLog LOG = GkLog.getLogger(JoglViewerServiceImpl.class);
    /** SERVICE_ID */
    private static final String SERVICE_ID = "org.goko.viewer.jogl";
    /** The current controller service*/
    private IFourAxisControllerAdapter controllerAdapter;
    /** The coordinate system adapter */
    private ICoordinateSystemAdapter coordinateSystemAdapter;
    /** Jog service */
    private IContinuousJogService continuousJogService;
    /** GCode execution monitor service */
    private IGCodeExecutionMonitorService executionMonitorService;
    /** The workspace service */
    private IWorkspaceService workspaceService;
    /** Bind camera on tool position ? */
    private boolean lockCameraOnTool;

    private IGCodeProviderRenderer gcodeRenderer;
    private BoundsRenderer boundsRenderer;
    private CoordinateSystemSetRenderer coordinateSystemRenderer;
    private GridRenderer gridRenderer;
    private FourAxisRenderer zeroRenderer;
    private BoundingTuple6b bounds;
    private KeyboardJogAdatper keyboardJogAdapter;
    private ToolRenderer toolRenderer;
    private Font jogWarnFont;

    /** (inheritDoc)
     * @see org.goko.core.common.service.IGokoService#getServiceId()
     */
    @Override
    public String getServiceId() throws GkException {
        return SERVICE_ID;
    }

    /** (inheritDoc)
     * @see org.goko.core.common.service.IGokoService#start()
     */
    @Override
    public void start() throws GkException {
        JoglViewerPreference.getInstance().addPropertyChangeListener(this);
        GokoPreference.getInstance().addPropertyChangeListener(this);

        jogWarnFont = new Font("SansSerif", Font.BOLD, 16);
        LOG.info("Starting " + this.getServiceId());
        this.gridRenderer = new GridRenderer();
        addRenderer(gridRenderer);
        TextRenderer xTextRenderer = new TextRenderer("X", 2, new Point3d(10, -0.1, 0),
                TextRenderer.MIDDLE | TextRenderer.LEFT);
        xTextRenderer.setColor(1, 0, 0, 1);
        addRenderer(new ArrowRenderer(new Point3d(10, 0, 0), new Vector3d(1, 0, 0), new Vector3d(0, 1, 0),
                new Color4f(1, 0, 0, 1)));
        TextRenderer yTextRenderer = new TextRenderer("Y", 2, new Point3d(-0.5, 10, 0),
                TextRenderer.BOTTOM | TextRenderer.LEFT);
        yTextRenderer.setColor(0, 1, 0, 1);
        addRenderer(new ArrowRenderer(new Point3d(0, 10, 0), new Vector3d(0, 1, 0), new Vector3d(1, 0, 0),
                new Color4f(0, 1, 0, 1)));
        TextRenderer zTextRenderer = new TextRenderer("Z", 2, new Point3d(-0.5, 0, 10), new Vector3d(1, 0, 0),
                new Vector3d(0, 0, 1), TextRenderer.BOTTOM | TextRenderer.LEFT);
        addRenderer(new ArrowRenderer(new Point3d(0, 0, 10), new Vector3d(0, 0, 1), new Vector3d(1, 0, 0),
                new Color4f(0, 0, 1, 1)));
        zTextRenderer.setColor(0, 0, 1, 1);
        addRenderer(xTextRenderer);
        addRenderer(yTextRenderer);
        addRenderer(zTextRenderer);
        zeroRenderer = new FourAxisRenderer(10, JoglViewerPreference.getInstance().getRotaryAxisDirection(),
                new Color3f(1, 0, 0), new Color3f(0, 1, 0), new Color3f(0, 0, 1), new Color3f(1, 1, 0));
        zeroRenderer.setDisplayRotaryAxis(JoglViewerPreference.getInstance().isRotaryAxisEnabled());
        addRenderer(zeroRenderer);
        boundsRenderer = new BoundsRenderer(null);
        addRenderer(boundsRenderer);
    }

    /** (inheritDoc)
     * @see org.goko.core.common.service.IGokoService#stop()
     */
    @Override
    public void stop() throws GkException {

    }

    @Override
    public void renderGCode(IGCodeProvider provider) throws GkException {
        if (gcodeRenderer != null) {
            removeRenderer(gcodeRenderer);
            executionMonitorService.removeExecutionListener(gcodeRenderer);
            gcodeRenderer.destroy();
        }
        gcodeRenderer = new RotaryAxisAdapter(this.controllerAdapter, new DefaultGCodeProviderRenderer(provider));
        executionMonitorService.addExecutionListener(gcodeRenderer);
        bounds = provider.getBounds();
        if (boundsRenderer != null) {
            removeRenderer(boundsRenderer);
        }
        boundsRenderer = new BoundsRenderer(provider.getBounds());
        addRenderer(boundsRenderer);
        addRenderer(gcodeRenderer);

    }

    /**<
     * @return the controllerService
     */
    public IFourAxisControllerAdapter getControllerAdapter() {
        return controllerAdapter;
    }

    /**
     * @param controllerService the controllerService to set
     */
    public void setControllerAdapter(IThreeAxisControllerAdapter controllerService) throws GkException {
        if (controllerService instanceof IFourAxisControllerAdapter) {
            setControllerAdapter((IFourAxisControllerAdapter) controllerService);
        } else {
            setControllerAdapter(new ThreeToFourAxisAdapterWrapper(controllerService));
        }
    }

    /**
     * @param controllerService the controllerService to set
     * @throws GkException GkException 
     */
    public void setControllerAdapter(IFourAxisControllerAdapter controllerService) throws GkException {
        this.controllerAdapter = controllerService;
        if (toolRenderer == null) {
            toolRenderer = new ToolRenderer(getControllerAdapter());
            addRenderer(toolRenderer);
        }
    }

    protected void applyRotationAngle(PMVMatrix matrix) throws GkException {
        double angle = controllerAdapter.getA().doubleValue();
        Vector3d rotaryVector = new Vector3d(
                JoglViewerPreference.getInstance().getRotaryAxisDirection().getVector3f());
        PMVMatrix rotMatrix = new PMVMatrix();
        rotMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
        rotMatrix.glLoadIdentity();
        rotMatrix.glRotatef((float) -angle, (float) rotaryVector.x, (float) rotaryVector.y, (float) rotaryVector.z);
        rotMatrix.update();
        matrix.glMultMatrixf(rotMatrix.glGetMvMatrixf());
        matrix.update();
    }

    /**
     * Clear the current canvas
     * @param gl the GL2
     */
    private void clear(GL3 gl) {
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
    }

    private Point3d getToolPosition() {
        Point3d p = new Point3d();
        try {
            Unit<Length> targetLengthUnit = GokoPreference.getInstance().getLengthUnit();
            p.x = getControllerAdapter().getX().to(targetLengthUnit).doubleValue();
            p.y = getControllerAdapter().getY().to(targetLengthUnit).doubleValue();
            p.z = getControllerAdapter().getZ().to(targetLengthUnit).doubleValue();
        } catch (GkException e) {
            LOG.error(e);
        }
        return p;
    }

    /** (inheritDoc)
     * @see javax.media.opengl.GLEventListener#dispose(javax.media.opengl.GLAutoDrawable)
     */
    @Override
    public void dispose(GLAutoDrawable arg0) {

    }

    /**
     * @return the lockCameraOnTool
     */
    @Override
    public boolean isLockCameraOnTool() {
        return lockCameraOnTool;
    }

    /**
     * @param lockCameraOnTool the lockCameraOnTool to set
     */
    @Override
    public void setLockCameraOnTool(boolean lockCameraOnTool) {
        this.lockCameraOnTool = lockCameraOnTool;
    }

    /**
     * @return the workspaceService
     */
    public IWorkspaceService getWorkspaceService() {
        return workspaceService;
    }

    /**
     * @param workspaceService the workspaceService to set
     * @throws GkException
     */
    public void setWorkspaceService(IWorkspaceService workspaceService) throws GkException {
        this.workspaceService = workspaceService;
        this.workspaceService.addWorkspaceListener(this);
    }

    /** (inheritDoc)
     * @see org.goko.core.workspace.service.IWorkspaceListener#onGCodeProviderEvent(org.goko.core.workspace.service.GCodeProviderEvent)
     */
    @Override
    public void onGCodeProviderEvent(GCodeProviderEvent event) throws GkException {
        if (event.getType() == GCodeProviderEventType.CURRENT_UPDATE) {
            if (getWorkspaceService().getCurrentGCodeProvider() != null) {
                this.renderGCode(getWorkspaceService().getCurrentGCodeProvider());
            }
        }
    }

    /**
     * @return the coordinateSystemAdapter
     */
    @Override
    public ICoordinateSystemAdapter getCoordinateSystemAdapter() {
        return coordinateSystemAdapter;
    }

    /**
     * @param coordinateSystemAdapter the coordinateSystemAdapter to set
     * @throws GkException
     */
    public void setCoordinateSystemAdapter(ICoordinateSystemAdapter coordinateSystemAdapter) throws GkException {
        this.coordinateSystemAdapter = coordinateSystemAdapter;
        if (this.coordinateSystemRenderer == null) {
            this.coordinateSystemRenderer = new CoordinateSystemSetRenderer();
            addRenderer(coordinateSystemRenderer);
        }
        this.coordinateSystemRenderer.setAdapter(coordinateSystemAdapter);
    }

    /**
     * @return the continuousJogService
     */
    public IContinuousJogService getContinuousJogService() {
        return continuousJogService;
    }

    /**
     * @param continuousJogService the continuousJogService to set
     */
    public void setContinuousJogService(IContinuousJogService continuousJogService) {
        this.continuousJogService = continuousJogService;
    }

    /**
     * @param executionMonitorService the executionMonitorService to set
     */
    public void setGCodeExecutionMonitorService(IGCodeExecutionMonitorService executionMonitorService) {
        this.executionMonitorService = executionMonitorService;
    }

    /** (inheritDoc)
     * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
     */
    @Override
    public void propertyChange(PropertyChangeEvent event) {
        super.propertyChange(event);
        try {
            zeroRenderer.setDisplayRotaryAxis(JoglViewerPreference.getInstance().isRotaryAxisEnabled());
            zeroRenderer.setRotationAxis(JoglViewerPreference.getInstance().getRotaryAxisDirection());
            // Update the grid
            if (StringUtils.equals(event.getProperty(), JoglViewerPreference.MAJOR_GRID_SPACING)
                    || StringUtils.equals(event.getProperty(), JoglViewerPreference.MINOR_GRID_SPACING)
                    || StringUtils.equals(event.getProperty(), GokoPreference.KEY_DISTANCE_UNIT)) {
                this.gridRenderer.destroy();
                this.gridRenderer = new GridRenderer();
                addRenderer(this.gridRenderer);
            }
            if (gcodeRenderer != null) {
                gcodeRenderer.update();
            }
        } catch (GkException e) {
            LOG.error(e);
        }
    }

    @Override
    public void zoomToFit() throws GkException {
        if (bounds != null) {
            getCamera().zoomToFit(bounds);
        }
    }

    @Override
    protected void onCanvasCreated(GokoJoglCanvas canvas) {
        if (continuousJogService != null) {
            this.keyboardJogAdapter = new KeyboardJogAdatper(getCanvas(), continuousJogService);
            canvas.addKeyListener(keyboardJogAdapter);
        }
    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.service.JoglSceneManager#drawOverlayData(java.awt.Graphics2D)
     */
    @Override
    protected void drawOverlayData(Graphics2D g2d) throws GkException {
        if (getCanvas().isKeyboardJogEnabled()) {
            // Draw a big red warning saying jog is enabled
            FontRenderContext frc = g2d.getFontRenderContext();
            String warn = "Keyboard jog enabled";
            GlyphVector gv = jogWarnFont.createGlyphVector(frc, warn);
            Rectangle bounds = gv.getPixelBounds(frc, 0, 0);
            int x = (getWidth() - bounds.width) / 2;
            int y = 5 + bounds.height;
            Rectangle2D bg = new Rectangle2D.Double(x - 5, 2, bounds.width + 15, bounds.height + 10);
            g2d.setFont(jogWarnFont);
            g2d.setColor(Color.RED);//new Color(0.9f,0,0,0.5f));
            g2d.fill(bg);
            g2d.setColor(Color.WHITE);
            g2d.drawString(warn, x, y);
        }

    }

    /** (inheritDoc)
     * @see org.goko.viewer.jogl.service.IJoglViewerService#setCoordinateSystemEnabled(org.goko.core.gcode.bean.commands.EnumCoordinateSystem, boolean)
     */
    @Override
    public void setCoordinateSystemEnabled(EnumCoordinateSystem cs, boolean enabled) {
        if (coordinateSystemRenderer != null) {
            coordinateSystemRenderer.setCoordinateSystemEnabled(cs, enabled);
        }
    }

}