Java tutorial
/* Copyright 2017 Will Winder This file is part of Universal Gcode Sender (UGS). UGS 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. UGS 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 UGS. If not, see <http://www.gnu.org/licenses/>. */ package com.willwinder.ugs.platform.surfacescanner; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.Iterables; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.util.gl2.GLUT; import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions; import com.willwinder.ugs.nbm.visualizer.shared.Renderable; import com.willwinder.universalgcodesender.model.Position; import com.willwinder.universalgcodesender.model.UnitUtils; import com.willwinder.universalgcodesender.model.UnitUtils.Units; import javax.vecmath.Point3d; /** * * @author wwinder */ public class AutoLevelPreview extends Renderable { private final GLUT glut; private ImmutableCollection<Position> positions; private Point3d[][] grid = null; // The maximum distance of a probe used for coloring. private double maxZ, minZ; private float high[] = { 0, 255, 0 }; // green private float low[] = { 255, 0, 0 }; // red public AutoLevelPreview(String title) { super(10, title); glut = new GLUT(); reloadPreferences(new VisualizerOptions()); } @Override public boolean rotate() { return true; } @Override public boolean center() { return true; } @Override public void init(GLAutoDrawable drawable) { } @Override public final void reloadPreferences(VisualizerOptions vo) { high = VisualizerOptions .colorToFloatArray(vo.getOptionForKey(VisualizerOptions.VISUALIZER_OPTION_LOW).value); low = VisualizerOptions .colorToFloatArray(vo.getOptionForKey(VisualizerOptions.VISUALIZER_OPTION_HIGH).value); } public void updateSettings(ImmutableCollection<Position> positions, Units gridUnits, final Point3d[][] grid, Point3d max, Point3d min) { if (positions != null && !positions.isEmpty()) { this.positions = positions; this.grid = grid; if (max != null) { this.maxZ = max.z; } if (min != null) { this.minZ = min.z; } } } @Override public void draw(GLAutoDrawable drawable, boolean idle, Point3d machineCoord, Point3d workCoord, Point3d objectMin, Point3d objectMax, double scaleFactor, Point3d mouseWorldCoordinates, Point3d rotation) { // Don't draw something invalid. if (positions == null || positions.isEmpty()) { return; } Position first = Iterables.getFirst(positions, null); Units unit = first.getUnits(); double objectX = objectMax.x - objectMin.x; double objectY = objectMax.y - objectMin.y; double diameter = Math.max(objectX * 0.005, objectY * 0.005); double minx, miny, minz; double maxx, maxy, maxz; minx = maxx = first.x; miny = maxy = first.y; minz = maxz = first.z; GL2 gl = drawable.getGL().getGL2(); gl.glPushMatrix(); // Scale inch to mm if needed double scale = UnitUtils.scaleUnits(unit, Units.MM); if (unit != Units.MM) { gl.glScaled(scale, scale, scale); } // Balls indicating the probe start locations. gl.glColor4fv(new float[] { 0.1f, 0.1f, 0.1f, 1.0f }, 0); for (Position p : positions) { gl.glPushMatrix(); gl.glTranslated(p.x, p.y, p.z); glut.glutSolidSphere(diameter / scale, 7, 7); // update min/max minx = Math.min(minx, p.x); maxx = Math.max(maxx, p.x); miny = Math.min(miny, p.y); maxz = Math.max(maxz, p.z); minz = Math.min(minz, p.z); maxy = Math.max(maxy, p.y); gl.glPopMatrix(); } // Outline of probe area gl.glPushMatrix(); gl.glTranslated((minx + maxx) / 2, (miny + maxy) / 2, (minz + maxz) / 2); gl.glScaled(maxx - minx, maxy - miny, maxz - minz); gl.glColor4fv(new float[] { 0.3f, 0, 0, 0.1f }, 0); glut.glutWireCube((float) 1.); gl.glPopMatrix(); drawProbedSurface(gl); gl.glPopMatrix(); } private void setColorForZ(GL2 gl, double zPos) { float ratio = (float) ((zPos - minZ) / (maxZ - minZ)); float r = ratio * high[0] + (1 - ratio) * low[0]; float g = ratio * high[1] + (1 - ratio) * low[1]; float b = ratio * high[2] + (1 - ratio) * low[2]; float a = ratio * high[3] + (1 - ratio) * low[3]; gl.glColor4f(r, g, b, a); } private void drawProbedSurface(GL2 gl) { if (this.grid == null) { return; } /* 0,5 ? ? ? ? ? 5,5 * ? ? ? ? \ * * ? ? ? x \ * * * ? ? x x \ 0,0 * * * * ? 5,0 */ gl.glBegin(GL2.GL_TRIANGLES); int xLen = this.grid.length; for (int x = 0; x < xLen - 1; x++) { if (this.grid[x] == null || this.grid[x + 1] == null) { continue; } for (int y = 0; y < this.grid[x].length - 1; y++) { Point3d pos1 = this.grid[x][y]; Point3d pos2 = this.grid[x + 1][y]; Point3d pos3 = this.grid[x][y + 1]; Point3d pos4 = this.grid[x + 1][y + 1]; // Bottom left of quad if (pos1 != null && pos2 != null && pos3 != null) { setColorForZ(gl, pos1.z); gl.glVertex3d(pos1.x, pos1.y, pos1.z); // Left Of Triangle (Front) setColorForZ(gl, pos3.z); gl.glVertex3d(pos3.x, pos3.y, pos3.z); // Top Of Triangle (Front) setColorForZ(gl, pos2.z); gl.glVertex3d(pos2.x, pos2.y, pos2.z); // Right Of Triangle (Front) } // Top right of quad if (pos2 != null && pos3 != null && pos4 != null) { setColorForZ(gl, pos4.z); gl.glVertex3d(pos4.x, pos4.y, pos4.z); // Right Of Triangle (Front) setColorForZ(gl, pos3.z); gl.glVertex3d(pos3.x, pos3.y, pos3.z); // Top Of Triangle (Front) setColorForZ(gl, pos2.z); gl.glVertex3d(pos2.x, pos2.y, pos2.z); // Left Of Triangle (Front) } } } gl.glEnd(); } }