/* * * Goko * Copyright (C) 2013 PsyKo * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.goko.tools.viewer.jogl.utils.render.grid; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import javax.media.opengl.GL; import javax.media.opengl.GL3; import javax.vecmath.Color3f; import javax.vecmath.Color4f; import javax.vecmath.Matrix4d; import javax.vecmath.Matrix4f; import javax.vecmath.Point4d; import javax.vecmath.Vector3f; import org.apache.commons.collections.CollectionUtils; import org.goko.core.common.exception.GkException; import org.goko.core.common.measure.quantity.Length; import org.goko.core.controller.IGCodeContextProvider; import org.goko.core.controller.event.IGCodeContextListener; import org.goko.core.gcode.rs274ngcv3.context.GCodeContext; import org.goko.core.log.GkLog; import org.goko.core.math.Tuple6b; import org.goko.tools.viewer.jogl.service.JoglUtils; import org.goko.tools.viewer.jogl.service.Layer; import org.goko.tools.viewer.jogl.shaders.EnumGokoShaderProgram; import org.goko.tools.viewer.jogl.shaders.ShaderLoader; import org.goko.tools.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer; /** * Draw the XYZ axis * * @author PsyKo * */ public class GridRenderer extends AbstractVboJoglRenderer implements IGCodeContextListener<GCodeContext>, IGridRenderer { private static final GkLog LOG = GkLog.getLogger(GridRenderer.class); private Length majorIncrement; private Length minorIncrement; private Matrix4f axisTransformMatrix; private Vector3f normal; private Vector3f horizontalVector; private Length horizontalMinimal; private Length horizontalMaximal; private Color4f horizontalColor; private Vector3f verticalVector; private Length verticalMinimal; private Length verticalMaximal; private Color4f verticalColor; private IGCodeContextProvider<GCodeContext> gcodeContextProvider; private Color4f majorUnitColor = new Color4f(0.4f, 0.4f, 0.4f,1f); private Color4f minorUnitColor = new Color4f(0.4f, 0.4f, 0.4f,1f); private Color4f originColor = new Color4f(0.8f, 0.8f, 0.8f,1f); private float majorOpacity; private float minorOpacity; private float axisOpacity; public GridRenderer(IGCodeContextProvider<GCodeContext> gcodeContextProvider){ this(new Vector3f(0f,0f,1f), Length.valueOf(10, JoglUtils.JOGL_UNIT), Length.valueOf(1, JoglUtils.JOGL_UNIT), new Vector3f(1f,0f,0f), Length.valueOf(-100, JoglUtils.JOGL_UNIT), Length.valueOf(100, JoglUtils.JOGL_UNIT), new Vector3f(0f,1f,0f), Length.valueOf(-100, JoglUtils.JOGL_UNIT), Length.valueOf(100, JoglUtils.JOGL_UNIT), new Color3f(0.4f, 0.4f, 0.4f), new Color3f(0.4f, 0.4f, 0.4f), 0.5f, 0.5f, 0.5f); this.gcodeContextProvider = gcodeContextProvider; if(this.gcodeContextProvider != null){ gcodeContextProvider.addObserver(this); } } /** * @param normal * @param majorIncrement * @param minorIncrement * @param horizontalVector * @param horizontalMinimal * @param horizontalMaximal * @param verticalVector * @param verticalMinimal * @param verticalMaximal * @param majorUnitColor * @param minorUnitColor * @param originColor * @param majorOpacity * @param minorOpacity * @param axisOpacity */ public GridRenderer(Vector3f normal, Length majorIncrement, Length minorIncrement, Vector3f horizontalVector, Length horizontalMinimal, Length horizontalMaximal, Vector3f verticalVector, Length verticalMinimal, Length verticalMaximal, Color3f majorUnitColor, Color3f minorUnitColor, float majorOpacity, float minorOpacity, float axisOpacity) { super(GL.GL_LINES, COLORS | VERTICES); this.setLayerId(Layer.LAYER_GRIDS); this.majorIncrement = majorIncrement; this.minorIncrement = minorIncrement; this.normal = new Vector3f(normal); this.horizontalVector = horizontalVector; this.horizontalMinimal = horizontalMinimal; this.horizontalMaximal = horizontalMaximal; this.verticalVector = verticalVector; this.verticalMinimal = verticalMinimal; this.verticalMaximal = verticalMaximal; this.majorUnitColor = new Color4f(majorUnitColor.x,majorUnitColor.y,majorUnitColor.z,majorOpacity); this.minorUnitColor = new Color4f(minorUnitColor.x,minorUnitColor.y,minorUnitColor.z,minorOpacity); this.majorOpacity = majorOpacity; this.minorOpacity = minorOpacity; this.axisOpacity = axisOpacity; buildMatrix(); setUseAlpha(true); } // /** // * Constructor // */ // public GridRenderer(Tuple6b start, Tuple6b end, Length majorIncrement, Length minorIncrement, Color3f majorColor, Color3f minorColor, float minorOpacity, float majorOpacity, float axisOpacity, Vector4f normal) { // super(GL.GL_LINES, COLORS | VERTICES); // this.setLayerId(Layer.LAYER_GRIDS); // this.majorIncrement = majorIncrement.to(JoglUtils.JOGL_UNIT); // this.minorIncrement = minorIncrement.to(JoglUtils.JOGL_UNIT); // this.majorUnitColor = new Color4f(majorColor.x,majorColor.y,majorColor.z,majorOpacity); // this.minorUnitColor = new Color4f(minorColor.x,minorColor.y,minorColor.z,minorOpacity); // this.originColor.w = axisOpacity; // this.minorOpacity = minorOpacity; // this.majorOpacity = majorOpacity; // this.axisOpacity = axisOpacity; // this.normal = new Vector3f(normal.x, normal.y, normal.z); // buildMatrix(); // setUseAlpha(true); // } private void buildGrid() throws GkException{ buildMatrix(); List<Point4d> lstVertices = new ArrayList<Point4d>(); List<Color4f> lstColors = new ArrayList<Color4f>(); Matrix4d invAxisTransformMatrix = new Matrix4d(axisTransformMatrix); invAxisTransformMatrix.invert(); double hMin = horizontalMinimal.doubleValue(JoglUtils.JOGL_UNIT); double hMax = horizontalMaximal.doubleValue(JoglUtils.JOGL_UNIT); double vMin = verticalMinimal.doubleValue(JoglUtils.JOGL_UNIT); double vMax = verticalMaximal.doubleValue(JoglUtils.JOGL_UNIT); int hStart = horizontalMinimal.divide(majorIncrement).setScale(0, RoundingMode.DOWN).intValue(); int hEnd = horizontalMaximal.divide(majorIncrement).setScale(0, RoundingMode.DOWN).intValue(); int nbMinorPerMajor = (int) majorIncrement.divide(minorIncrement).floatValue(); double dMajorIncrement = majorIncrement.doubleValue(JoglUtils.JOGL_UNIT); double dMinorIncrement = minorIncrement.doubleValue(JoglUtils.JOGL_UNIT); // Draw origin Point4d originHorizontalMin = new Point4d( hMin, 0, 0 , 1); Point4d originHorizontalMax = new Point4d( hMax, 0, 0 , 1); Point4d originVerticalMin = new Point4d( 0, vMin, 0 , 1); Point4d originVerticalMax = new Point4d( 0, vMax, 0 , 1); addVertice(originHorizontalMin, lstVertices, invAxisTransformMatrix); addVertice(originHorizontalMax, lstVertices, invAxisTransformMatrix); addVertice(originVerticalMin, lstVertices, invAxisTransformMatrix); addVertice(originVerticalMax, lstVertices, invAxisTransformMatrix); lstColors.add(originColor); lstColors.add(originColor); lstColors.add(originColor); lstColors.add(originColor); // Let's build vertical major rulers for (int h = hStart; h <= hEnd; h++) { double horizontal = dMajorIncrement * h; Point4d p1 = new Point4d( horizontal, vMin, 0 , 1); Point4d p2 = new Point4d( horizontal, vMax, 0 , 1); addVertice(p1, lstVertices, invAxisTransformMatrix); addVertice(p2, lstVertices, invAxisTransformMatrix); lstColors.add(majorUnitColor); lstColors.add(majorUnitColor); for(int s = 1; s < nbMinorPerMajor && h < hEnd; s++){ Point4d s1 = new Point4d( horizontal + dMinorIncrement * s, vMin, 0 , 1); Point4d s2 = new Point4d( horizontal + dMinorIncrement * s, vMax, 0 , 1); addVertice(s1, lstVertices, invAxisTransformMatrix); addVertice(s2, lstVertices, invAxisTransformMatrix); lstColors.add(minorUnitColor); lstColors.add(minorUnitColor); } } int vStart = verticalMinimal.divide(majorIncrement).setScale(0, RoundingMode.DOWN).intValue(); int vEnd = verticalMaximal.divide(majorIncrement).setScale(0, RoundingMode.DOWN).intValue(); // Let's build horizontal major rulers for (int v = vStart; v <= vEnd; v++) { double vertical = dMajorIncrement * v; Point4d p1 = new Point4d( hMin, vertical, 0 , 1); Point4d p2 = new Point4d( hMax, vertical, 0 , 1); addVertice(p1, lstVertices, invAxisTransformMatrix); addVertice(p2, lstVertices, invAxisTransformMatrix); lstColors.add(majorUnitColor); lstColors.add(majorUnitColor); for(int s = 1; s < nbMinorPerMajor && v < vEnd; s++){ Point4d s1 = new Point4d( hMin, vertical + dMinorIncrement * s, 0 , 1); Point4d s2 = new Point4d( hMax, vertical + dMinorIncrement * s, 0 , 1); addVertice(s1, lstVertices, invAxisTransformMatrix); addVertice(s2, lstVertices, invAxisTransformMatrix); lstColors.add(minorUnitColor); lstColors.add(minorUnitColor); } } if(horizontalColor != null){ Point4d p1 = new Point4d( hMin, 0, 0 , 1); Point4d p2 = new Point4d( hMax, 0, 0 , 1); addVertice(p1, lstVertices, invAxisTransformMatrix); addVertice(p2, lstVertices, invAxisTransformMatrix); lstColors.add(horizontalColor); lstColors.add(horizontalColor); } if(verticalColor != null){ Point4d p1 = new Point4d( 0, vMin, 0 , 1); Point4d p2 = new Point4d( 0, vMax, 0 , 1); addVertice(p1, lstVertices, invAxisTransformMatrix); addVertice(p2, lstVertices, invAxisTransformMatrix); lstColors.add(verticalColor); lstColors.add(verticalColor); } setVerticesCount(CollectionUtils.size(lstVertices)); setColorsBuffer(JoglUtils.buildFloatBuffer4f(lstColors)); setVerticesBuffer(JoglUtils.buildFloatBuffer4d(lstVertices)); } private void addVertice(Point4d p, List<Point4d> buffer, Matrix4d invMatrix){ if(invMatrix != null){ invMatrix.transform(p); } buffer.add(p); } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#buildGeometry() */ @Override protected void buildGeometry() throws GkException { buildGrid(); } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.internal.AbstractVboJoglRenderer#loadShaderProgram(javax.media.opengl.GL3) */ @Override protected int loadShaderProgram(GL3 gl) throws GkException { return ShaderLoader.loadShader(gl, EnumGokoShaderProgram.LINE_SHADER); } @Override protected void updateShaderData(GL3 gl) throws GkException { super.updateShaderData(gl); gl.glLineWidth(1); gl.glEnable(GL3.GL_LINE_SMOOTH); } /** (inheritDoc) * @see org.goko.core.controller.event.IGCodeContextListener#onGCodeContextEvent(org.goko.core.gcode.element.IGCodeContext) */ @Override public void onGCodeContextEvent(GCodeContext context) { try { updateGeometry(); } catch (GkException e) { LOG.error(e); } } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#getMinorOpacity() */ @Override public float getMinorOpacity() { return minorOpacity; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setMinorOpacity(float) */ @Override public void setMinorOpacity(float opacity) { this.minorOpacity = opacity; this.minorUnitColor.w = opacity; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#getMajorOpacity() */ @Override public float getMajorOpacity() { return majorOpacity; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setMajorOpacity(float) */ @Override public void setMajorOpacity(float opacity) { this.majorOpacity = opacity; this.majorUnitColor.w = opacity; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#getAxisOpacity() */ @Override public float getAxisOpacity() { return axisOpacity; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setAxisOpacity(float) */ @Override public void setAxisOpacity(float opacity) { this.axisOpacity = opacity; this.originColor.w = opacity; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#getMajorIncrement() */ @Override public Length getMajorIncrement() { return majorIncrement; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setMajorIncrement(org.goko.core.common.measure.quantity.Length) */ @Override public void setMajorIncrement(Length majorIncrement) { this.majorIncrement = majorIncrement; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#getMinorIncrement() */ @Override public Length getMinorIncrement() { return minorIncrement; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setMinorIncrement(org.goko.core.common.measure.quantity.Length) */ @Override public void setMinorIncrement(Length minorIncrement) { this.minorIncrement = minorIncrement; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setMajorUnitColor(javax.vecmath.Color3f) */ @Override public void setMajorUnitColor(Color3f majorUnitColor) { this.majorUnitColor.x = majorUnitColor.x; this.majorUnitColor.y = majorUnitColor.y; this.majorUnitColor.z = majorUnitColor.z; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setMinorUnitColor(javax.vecmath.Color3f) */ @Override public void setMinorUnitColor(Color3f minorUnitColor) { this.minorUnitColor.x = minorUnitColor.x; this.minorUnitColor.y = minorUnitColor.y; this.minorUnitColor.z = minorUnitColor.z; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#getOriginColor() */ @Override public Color4f getOriginColor() { return originColor; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setOriginColor(javax.vecmath.Color4f) */ @Override public void setOriginColor(Color4f originColor) { this.originColor = originColor; } private void buildMatrix(){ this.normal.normalize(); this.horizontalVector.normalize(); this.verticalVector.normalize(); //this.verticalVector = new Vector3f(); //this.verticalVector.cross(normal, horizontalVector); this.axisTransformMatrix = new Matrix4f(new float[]{horizontalVector.x, horizontalVector.y, horizontalVector.z, 0.0f, verticalVector.x, verticalVector.y, verticalVector.z, 0.0f, normal.x, normal.y, normal.z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}); } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#getNormal() */ @Override public Vector3f getNormal() { return normal; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setNormal(javax.vecmath.Vector4f) */ @Override public void setNormal(Vector3f normal) { this.normal = normal; buildMatrix(); } /** * @return the majorUnitColor */ public Color4f getMajorUnitColor() { return majorUnitColor; } /** * @param majorUnitColor the majorUnitColor to set */ public void setMajorUnitColor(Color4f majorUnitColor) { this.majorUnitColor = majorUnitColor; } /** * @return the minorUnitColor */ public Color4f getMinorUnitColor() { return minorUnitColor; } /** * @param minorUnitColor the minorUnitColor to set */ public void setMinorUnitColor(Color4f minorUnitColor) { this.minorUnitColor = minorUnitColor; } /** * @return the axisTransformMatrix */ public Matrix4f getAxisTransformMatrix() { return axisTransformMatrix; } /** * @param axisTransformMatrix the axisTransformMatrix to set */ public void setAxisTransformMatrix(Matrix4f axisTransformMatrix) { this.axisTransformMatrix = axisTransformMatrix; } /** * @return the horizontalVector */ public Vector3f getHorizontalVector() { return horizontalVector; } /** * @param horizontalVector the horizontalVector to set */ public void setHorizontalVector(Vector3f horizontalVector) { this.horizontalVector = horizontalVector; buildMatrix(); } /** * @return the verticalVector */ public Vector3f getVerticalVector() { return verticalVector; } /** * @param verticalVector the verticalVector to set */ public void setVerticalVector(Vector3f verticalVector) { this.verticalVector = verticalVector; buildMatrix(); } /** * @return the horizontalMinimal */ public Length getHorizontalMinimal() { return horizontalMinimal; } /** * @param horizontalMinimal the horizontalMinimal to set */ public void setHorizontalMinimal(Length horizontalMinimal) { this.horizontalMinimal = horizontalMinimal; } /** * @return the horizontalMaximal */ public Length getHorizontalMaximal() { return horizontalMaximal; } /** * @param horizontalMaximal the horizontalMaximal to set */ public void setHorizontalMaximal(Length horizontalMaximal) { this.horizontalMaximal = horizontalMaximal; } /** * @return the verticalMinimal */ public Length getVerticalMinimal() { return verticalMinimal; } /** * @param verticalMinimal the verticalMinimal to set */ public void setVerticalMinimal(Length verticalMinimal) { this.verticalMinimal = verticalMinimal; } /** * @return the verticalMaximal */ public Length getVerticalMaximal() { return verticalMaximal; } /** * @param verticalMaximal the verticalMaximal to set */ public void setVerticalMaximal(Length verticalMaximal) { this.verticalMaximal = verticalMaximal; } /** * @return the horizontalColor */ public Color4f getHorizontalColor() { return horizontalColor; } /** * @param horizontalColor the horizontalColor to set */ public void setHorizontalColor(Color4f horizontalColor) { this.horizontalColor = horizontalColor; } /** * @return the verticalColor */ public Color4f getVerticalColor() { return verticalColor; } /** * @param verticalColor the verticalColor to set */ public void setVerticalColor(Color4f verticalColor) { this.verticalColor = verticalColor; } /** (inheritDoc) * @see org.goko.tools.viewer.jogl.utils.render.grid.IGridRenderer#setWorldBounds(org.goko.core.math.Tuple6b, org.goko.core.math.Tuple6b) */ @Override public void setWorldBounds(Tuple6b workMin, Tuple6b workMax) { Vector3f workMinJogl = new Vector3f(workMin.min(workMax).toVector3d(JoglUtils.JOGL_UNIT)); Vector3f workMaxJogl = new Vector3f(workMax.max(workMin).toVector3d(JoglUtils.JOGL_UNIT)); Matrix4f invMatrix = new Matrix4f(getAxisTransformMatrix()); invMatrix.invert(); invMatrix.transform(workMinJogl); invMatrix.transform(workMaxJogl); setHorizontalMinimal( Length.valueOf(BigDecimal.valueOf(workMinJogl.dot(getHorizontalVector())), JoglUtils.JOGL_UNIT)); setHorizontalMaximal( Length.valueOf(BigDecimal.valueOf(workMaxJogl.dot(getHorizontalVector())), JoglUtils.JOGL_UNIT)); setVerticalMinimal( Length.valueOf(BigDecimal.valueOf(workMinJogl.dot(getVerticalVector())), JoglUtils.JOGL_UNIT)); setVerticalMaximal( Length.valueOf(BigDecimal.valueOf(workMaxJogl.dot(getVerticalVector())), JoglUtils.JOGL_UNIT)); } }