diff --git a/ugs-platform/ugs-platform-visualizer/pom.xml b/ugs-platform/ugs-platform-visualizer/pom.xml
index 0abc833807..01bf9a202d 100644
--- a/ugs-platform/ugs-platform-visualizer/pom.xml
+++ b/ugs-platform/ugs-platform-visualizer/pom.xml
@@ -23,6 +23,15 @@
com.willwinder.ugs.nbm.visualizer.shared
com.willwinder.ugs.nbm.visualizer.options
com.willwinder.ugs.nbm.visualizer.renderables
+ org.apache.commons.io
+ javax.xml.datatype
+ org.w3c.dom
+ org.w3c.dom.ls
+ org.xml.sax
+ javax.xml.parsers
+ org.w3c.dom.bootstrap
+ org.xml.sax.helpers
+ com.jogamp.opengl
@@ -64,6 +73,13 @@
${netbeans.version}
jar
+
+ org.netbeans.modules
+ org-openide-util-ui-svg
+ ${netbeans.version}
+ jar
+ test
+
${project.groupId}
ugs-platform-ugslib
@@ -91,5 +107,72 @@
ugs-platform-ugscore
${project.version}
+
+
+
+ com.neuronrobotics
+ JavaCad
+ 1.8.8
+
+
+ eu.mihosoft.vvecmath
+ vvecmath
+ 0.4.0
+
+
+ org.openjfx
+ javafx-graphics
+ 17.0.8
+
+
+ org.openjfx
+ javafx-base
+ 17.0.8
+
+
+ org.openjfx
+ javafx-fxml
+ 17.0.9
+
+
+ org.openjfx
+ javafx-controls
+ 17.0.9
+
+
+ org.openjfx
+ javafx-swing
+ 17.0.9
+
+
+
+
+ org.locationtech.jts
+ jts-core
+ ${jts.version}
+
+
+
+
+ org.apache.xmlgraphics
+ batik-all
+ ${batik.version}
+
+
+ javax.vecmath
+ vecmath
+ 1.5.2
+
+
+
+ commons-io
+ commons-io
+ 2.7
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/RendererInputHandler.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/RendererInputHandler.java
index aee1d98acd..5fd6e383cf 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/RendererInputHandler.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/RendererInputHandler.java
@@ -63,8 +63,8 @@ This file is part of Universal Gcode Sender (UGS).
public class RendererInputHandler implements
WindowListener, MouseWheelListener, MouseMotionListener,
MouseListener, KeyListener, PreferenceChangeListener, UGSEventListener {
- private static final int HIGH_FPS = 15;
- private static final int LOW_FPS = 4;
+ private final int highFps;
+ private final int lowFps;
private final GcodeRenderer gcodeRenderer;
private final AnimatorBase animator;
private final BackendAPI backend;
@@ -76,11 +76,13 @@ public class RendererInputHandler implements
private Position selectionStart = null;
private Position selectionEnd = null;
- public RendererInputHandler(GcodeRenderer gr, AnimatorBase a, BackendAPI backend) {
+ public RendererInputHandler(GcodeRenderer gr, AnimatorBase a, BackendAPI backend, int lowFps, int highFps) {
gcodeRenderer = gr;
animator = a;
this.backend = backend;
settings = backend.getSettings();
+ this.highFps = highFps;
+ this.lowFps = lowFps;
gcodeModel = new GcodeModel(Localization.getString("platform.visualizer.renderable.gcode-model"), backend);
sizeDisplay = new SizeDisplay(Localization.getString("platform.visualizer.renderable.gcode-model-size"));
@@ -271,7 +273,7 @@ public void mouseClicked(MouseEvent e) {
*/
@Override
public void mousePressed(MouseEvent e) {
- setFPS(HIGH_FPS);
+ setFPS(highFps);
// Zoom
if (e.getButton() == MouseEvent.BUTTON1 && e.isMetaDown()) {
selecting = true;
@@ -282,7 +284,7 @@ public void mousePressed(MouseEvent e) {
@Override
public void mouseReleased(MouseEvent e) {
- setFPS(LOW_FPS);
+ setFPS(lowFps);
// Finish selecting.
if (selecting) {
@@ -317,7 +319,7 @@ public void keyTyped(KeyEvent ke) {
*/
@Override
public void keyPressed(KeyEvent ke) {
- setFPS(HIGH_FPS);
+ setFPS(highFps);
int DELTA_SIZE = 1;
@@ -358,7 +360,7 @@ public void keyPressed(KeyEvent ke) {
*/
@Override
public void keyReleased(KeyEvent ke) {
- setFPS(LOW_FPS);
+ setFPS(lowFps);
}
public void dispose() {
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/NewtVisualizationPanel.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/NewtVisualizationPanel.java
index b7b8a724e2..292a36540b 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/NewtVisualizationPanel.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/NewtVisualizationPanel.java
@@ -24,7 +24,7 @@ This file is part of Universal Gcode Sender (UGS).
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLException;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.FPSAnimator;
import com.willwinder.ugs.nbm.visualizer.RendererInputHandler;
import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions;
import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_NEWT_SAMPLES;
@@ -134,8 +134,8 @@ private NewtCanvasAWT makeWindow() throws GLException {
lock.lock();
lock.unlock();
- Animator animator = new Animator(glWindow);
- this.rih = new RendererInputHandler(renderer, animator, backend);
+ FPSAnimator animator = new FPSAnimator(glWindow, 60);
+ this.rih = new RendererInputHandler(renderer, animator, backend, 30, 60);
Preferences pref = NbPreferences.forModule(VisualizerOptionsPanel.class);
pref.addPreferenceChangeListener(this.rih);
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/VisualizationPanel.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/VisualizationPanel.java
index 69a7b5aa68..47fb38e0c8 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/VisualizationPanel.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/jogl/VisualizationPanel.java
@@ -99,7 +99,7 @@ private GLJPanel makeWindow() throws GLException {
}
FPSAnimator animator = new FPSAnimator(p, 15);
- this.rih = new RendererInputHandler(renderer, animator, backend);
+ this.rih = new RendererInputHandler(renderer, animator, backend, 4, 15);
Preferences pref = NbPreferences.forModule(VisualizerOptionsPanel.class);
pref.addPreferenceChangeListener(this.rih);
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Grid.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Grid.java
index 55675adbc3..5f3a106f59 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Grid.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Grid.java
@@ -20,14 +20,17 @@ This file is part of Universal Gcode Sender (UGS).
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.GLAutoDrawable;
import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions;
+import com.willwinder.ugs.nbm.visualizer.shader.PlainShader;
+import com.willwinder.ugs.nbm.visualizer.shared.VertexObjectRenderable;
+import com.willwinder.universalgcodesender.model.Position;
+
import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_GRID;
import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_X;
import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_XY_GRID;
import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_Y;
import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_Z;
-import com.willwinder.ugs.nbm.visualizer.shared.VertexObjectRenderable;
-import com.willwinder.universalgcodesender.model.Position;
/**
* @author wwinder
@@ -39,7 +42,7 @@ public class Grid extends VertexObjectRenderable {
private float[] zAxisColor;
public Grid(String title) {
- super(6, title, VISUALIZER_OPTION_GRID);
+ super(6, title, VISUALIZER_OPTION_GRID, new PlainShader());
reloadPreferences(new VisualizerOptions());
}
@@ -53,7 +56,8 @@ public final void reloadPreferences(VisualizerOptions vo) {
}
@Override
- public void render(GL2 gl) {
+ public void render(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
gl.glLineWidth(1.2f);
gl.glDisable(GL.GL_DEPTH_TEST);
gl.glDrawArrays(GL.GL_LINES, 0, getVertexCount());
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/OrientationCube.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/OrientationCube.java
index b01539d830..9b2610e836 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/OrientationCube.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/OrientationCube.java
@@ -19,175 +19,151 @@ This file is part of Universal Gcode Sender (UGS).
package com.willwinder.ugs.nbm.visualizer.renderables;
-import static com.jogamp.opengl.GL.GL_CULL_FACE;
-import static com.jogamp.opengl.GL.GL_DEPTH_TEST;
+import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
-import static com.jogamp.opengl.GL2ES3.GL_QUADS;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
-import com.jogamp.opengl.util.awt.TextRenderer;
-import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_ORIENTATION_CUBE;
-import com.willwinder.ugs.nbm.visualizer.shared.Renderable;
+import com.jogamp.opengl.fixedfunc.GLPointerFunc;
+import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions;
+import com.willwinder.ugs.nbm.visualizer.shader.PlainShader;
+import com.willwinder.ugs.nbm.visualizer.shared.VertexObjectRenderable;
import com.willwinder.universalgcodesender.model.Position;
+import eu.mihosoft.vrl.v3d.CSG;
+import eu.mihosoft.vrl.v3d.Cube;
+import eu.mihosoft.vrl.v3d.Polygon;
+import eu.mihosoft.vrl.v3d.RoundedCube;
+import eu.mihosoft.vrl.v3d.Transform;
+import eu.mihosoft.vrl.v3d.Vector3d;
+import javafx.scene.paint.Color;
+
+import java.util.List;
+import java.util.Optional;
-import java.awt.Font;
-import java.awt.geom.Rectangle2D;
+import static com.jogamp.opengl.GL.GL_DEPTH_TEST;
+import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_ORIENTATION_CUBE;
/**
* Draw a cube with the orientation labeled on the sides.
- *
+ *
* @author wwinder
*/
-public class OrientationCube extends Renderable {
- private final float size;
- private final float[] color = {0.8f, 0.8f, 0.8f};
- private final float[] border = {0.2f, 0.2f, 0.2f};
-
- private TextRenderer renderer;
- private float textScaleFactor;
-
- public OrientationCube(float s, String title) {
- super(Integer.MIN_VALUE, title, VISUALIZER_OPTION_ORIENTATION_CUBE);
- size = s;
- }
-
- @Override
- public boolean rotate() {
- return true;
- }
-
- @Override
- public boolean center() {
- return false;
- }
-
- @Override
- public void init(GLAutoDrawable drawable) {
- renderer = new TextRenderer(new Font("SansSerif", Font.PLAIN, 72));
- renderer.setColor(0.2f, 0.2f, 0.2f, 1f);
-
- // Compute the scale factor of the largest string which will make
- // them all fit on the faces of the cube
- Rectangle2D bounds = renderer.getBounds("Z+");
- float w = (float) bounds.getWidth();
-
- textScaleFactor = size / (w * 1.7f);
- }
-
- @Override
- public void draw(GLAutoDrawable drawable, boolean idle, Position machineCoord, Position workCoord, Position focusMin, Position focusMax, double scaleFactor, Position mouseCoordinates, Position rotation) {
- GL2 gl = drawable.getGL().getGL2();
-
- int ySize = drawable.getDelegatedDrawable().getSurfaceHeight();
- int xSize = drawable.getDelegatedDrawable().getSurfaceWidth();
-
- // Set viewport to the corner.
- float fromEdge = 0.8f;
- int squareSize = ySize-(int)(ySize*fromEdge);
- gl.glViewport(0, (int)(ySize*fromEdge), squareSize, squareSize);
-
- gl.glPushMatrix();
+public class OrientationCube extends VertexObjectRenderable {
+ private final CSG model;
+
+ protected void clear() {
+ super.clear();
+ }
+
+ public OrientationCube(String title) {
+ super(Integer.MIN_VALUE, title, VISUALIZER_OPTION_ORIENTATION_CUBE, new PlainShader());
+ reloadPreferences(new VisualizerOptions());
+ model = generateModel();
+ }
+
+ @Override
+ public boolean center() {
+ return false;
+ }
+
+ private CSG generateModel() {
+ double size = 0.5;
+
+ Color faceColor = Color.LIGHTGRAY;
+ Color cornerColor = Color.GRAY;
+
+ CSG cube = new Cube(size, size * 0.8, size * 0.8).toCSG()
+ .union(new Cube(size * 0.8, size * 0.8, size).toCSG())
+ .union(new Cube(size * 0.8, size, size * 0.8).toCSG())
+ .setColor(faceColor);
+
+ CSG corners = new RoundedCube(size).cornerRadius(0.03).toCSG().setColor(cornerColor);
+
+ CSG result = cube.union(corners);
+
+ CSG text = CSG.text("Z-", 1)
+ .setColor(Color.BLUE)
+ .transformed(new Transform().scale(0.01).rot(180, 0, 0).translate(-15, -10, 25));
+ result = result.dumbUnion(text);
+
+ text = CSG.text("Z+", 1)
+ .setColor(Color.BLUE)
+ .transformed(new Transform().scale(0.01).translate(-16, -10, 25));
+ result = result.dumbUnion(text);
+
+ text = CSG.text("Y+", 1)
+ .setColor(Color.GREEN)
+ .transformed(new Transform().scale(0.01).rot(90, 0, 180).translate(-16, -10, 25));
+ result = result.dumbUnion(text);
+
+ text = CSG.text("Y-", 1)
+ .setColor(Color.GREEN)
+ .transformed(new Transform().scale(0.01).rot(270, 0, 0).translate(-14, -10, 25));
+ result = result.dumbUnion(text);
+
+ text = CSG.text("X-", 1)
+ .setColor(Color.RED)
+ .transformed(new Transform().scale(0.01).rot(270, 90, 0).translate(-14, -10, 25));
+ result = result.dumbUnion(text);
+
+ text = CSG.text("X+", 1)
+ .setColor(Color.RED)
+ .transformed(new Transform().scale(0.01).rot(270, 270, 0).translate(-16, -10, 25));
+ result = result.dumbUnion(text);
+
+ return result.scale(0.8);
+ }
+
+ private void generateBuffers(CSG csg) {
+ List polygons = csg.triangulate().getPolygons();
+
+ for (Polygon polygon : polygons) {
+ Color color = Optional.ofNullable(polygon.getColor()).orElse(Color.GRAY);
+ float[] colorArray = new float[]{(float) color.getRed(), (float) color.getGreen(), (float) color.getBlue(), 1f};
+
+ Vector3d a = polygon.getPoints().get(0);
+ Vector3d b = polygon.getPoints().get(1);
+ Vector3d c = polygon.getPoints().get(2);
+ Vector3d normal = b.minus(a).cross(c.minus(a)).normalized();
+
+ polygon.getPoints().forEach(point -> {
+ addVertex(point.getX(), point.getY(), point.getZ());
+ addNormal(normal.getX(), normal.getY(), normal.getZ());
+ addColor(colorArray);
+ });
+ }
+ }
+
+ @Override
+ public void render(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ int ySize = drawable.getDelegatedDrawable().getSurfaceHeight();
+ int xSize = drawable.getDelegatedDrawable().getSurfaceWidth();
+
+ // Set viewport to the corner.
+ float fromEdge = 0.8f;
+ int squareSize = ySize - (int) (ySize * fromEdge);
+
+
+ gl.glViewport(0, (int) (ySize * fromEdge), squareSize, squareSize);
+
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
- gl.glOrtho(-0.5, 0.5, -0.5, 0.5, -0.5, 0.5); //, maxSide, maxSide, maxSide, maxSide, maxSide);
+ gl.glOrtho(-0.5, 0.5, -0.5, 0.5, -1, 2);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
-
- drawCube(gl);
- gl.glPopMatrix();
-
- gl.glViewport(0, 0, xSize, ySize);
- }
-
- private void drawCube(GL2 gl) {
- // Six faces of cube
- // Top face
- gl.glPushMatrix();
- gl.glRotatef(-90, 1, 0, 0);
- gl.glRotatef(180, 0, 0, 1);
- drawFace(gl, size, color, border, "Y+");
- gl.glPopMatrix();
-
- // Front face
- drawFace(gl, size, color, border, "Z+");
-
- // Right face
- gl.glPushMatrix();
- gl.glRotatef(90, 0, 1, 0);
-
- gl.glPushMatrix();
- gl.glRotatef(90, 0, 0, 1);
- drawFace(gl, size, color, border, "X+");
- gl.glPopMatrix();
-
- // Back face
- gl.glRotatef(90, 0, 1, 0);
- gl.glPushMatrix();
- gl.glRotatef(180, 0, 0, 1);
- drawFace(gl, size, color, border, "Z-");
- gl.glPopMatrix();
-
- // Left face
- gl.glRotatef(90, 0, 1, 0);
- gl.glRotatef(-90, 0, 0, 1);
- drawFace(gl, size, color, border, "X-");
- gl.glPopMatrix();
- // Bottom face
- gl.glPushMatrix();
- gl.glRotatef(90, 1, 0, 0);
- drawFace(gl, size, color, border, "Y-");
- gl.glPopMatrix();
- }
-
- private void drawFace(GL2 gl,
- float faceSize,
- float[] color,
- float[] border,
- String text) {
- float halfFaceSize = faceSize / 2;
- float borderSize = halfFaceSize * 0.8f;
- float layer2 = halfFaceSize + 0.001f;
- // Face is centered around the local coordinate system's z axis,
- // at a z depth of faceSize / 2
- gl.glColor3f(border[0], border[1], border[2]);
- gl.glBegin(GL_QUADS);
- gl.glVertex3f(-halfFaceSize, -halfFaceSize, halfFaceSize);
- gl.glVertex3f( halfFaceSize, -halfFaceSize, halfFaceSize);
- gl.glVertex3f( halfFaceSize, halfFaceSize, halfFaceSize);
- gl.glVertex3f(-halfFaceSize, halfFaceSize, halfFaceSize);
- gl.glEnd();
-
- gl.glColor3f(color[0], color[1], color[2]);
- gl.glBegin(GL_QUADS);
- gl.glVertex3f(-borderSize, -borderSize, layer2);
- gl.glVertex3f( borderSize, -borderSize, layer2);
- gl.glVertex3f( borderSize, borderSize, layer2);
- gl.glVertex3f(-borderSize, borderSize, layer2);
- gl.glEnd();
-
- // Now draw the overlaid text. In this setting, we don't want the
- // text on the backward-facing faces to be visible, so we enable
- // back-face culling; and since we're drawing the text over other
- // geometry, to avoid z-fighting we disable the depth test. We
- // could plausibly also use glPolygonOffset but this is simpler.
- // Note that because the TextRenderer pushes the enable state
- // internally we don't have to reset the depth test or cull face
- // bits after we're done.
- renderer.begin3DRendering();
- gl.glDisable(GL_DEPTH_TEST);
- gl.glEnable(GL_CULL_FACE);
- // Note that the defaults for glCullFace and glFrontFace are
- // GL_BACK and GL_CCW, which match the TextRenderer's definition
- // of front-facing text.
- Rectangle2D bounds = renderer.getBounds(text);
- float w = (float) bounds.getWidth();
- float h = (float) bounds.getHeight();
- renderer.draw3D(text,
- w / -2.0f * textScaleFactor,
- h / -2.0f * textScaleFactor,
- layer2,
- textScaleFactor);
- renderer.end3DRendering();
- gl.glDisable(GL_CULL_FACE);
- gl.glEnable(GL_DEPTH_TEST);
- }
+
+ gl.glEnable(GL_DEPTH_TEST);
+ int count = getVertexCount();
+ gl.glDrawArrays(GL.GL_TRIANGLES, 0, count);
+
+ gl.glDisableClientState(GLPointerFunc.GL_NORMAL_ARRAY);
+ gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
+ gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
+
+ gl.glViewport(0, 0, xSize, ySize);
+ }
+
+ @Override
+ public void reloadModel(GL2 gl, Position bottomLeft, Position topRight, double scaleFactor) {
+ generateBuffers(model);
+ }
}
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Plane.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Plane.java
index 28446c3e96..73ec254be4 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Plane.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/renderables/Plane.java
@@ -20,17 +20,20 @@ This file is part of Universal Gcode Sender (UGS).
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.GLAutoDrawable;
import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions;
-import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_PLANE_COLOR;
+import com.willwinder.ugs.nbm.visualizer.shader.PlainShader;
import com.willwinder.ugs.nbm.visualizer.shared.VertexObjectRenderable;
import com.willwinder.universalgcodesender.model.Position;
+import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_PLANE_COLOR;
+
public class Plane extends VertexObjectRenderable {
private float[] gridPlaneColor;
public Plane(String title) {
- super(7, title, VisualizerOptions.VISUALIZER_OPTION_PLANE);
+ super(7, title, VisualizerOptions.VISUALIZER_OPTION_PLANE, new PlainShader());
}
@Override
@@ -40,7 +43,8 @@ public void reloadPreferences(VisualizerOptions vo) {
}
@Override
- public void render(GL2 gl) {
+ public void render(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
gl.glDisable(GL.GL_DEPTH_TEST);
gl.glDrawArrays(GL.GL_TRIANGLES, 0, getVertexCount());
}
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/PlainShader.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/PlainShader.java
index 446296def0..26aa08f3a5 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/PlainShader.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/PlainShader.java
@@ -33,36 +33,54 @@ This file is part of Universal Gcode Sender (UGS).
* @author Joacim Breiler
*/
public class PlainShader implements Shader {
+ private final String vertexShader;
+ private final String fragmentShader;
private int shaderProgramId;
- private int shaderVertexIndex;
- private int shaderColorIndex;
+
+ public PlainShader() {
+ this("/shaders/plain.vert.glsl", "/shaders/plain.frag.glsl");
+ }
+
+ public PlainShader(String vertexShader, String fragmentShader) {
+ this.vertexShader = vertexShader;
+ this.fragmentShader = fragmentShader;
+ }
public void init(GL2 gl) {
try {
- InputStream vertexShaderInputStream = getClass().getResourceAsStream("/shaders/plain.vert.glsl");
+ InputStream vertexShaderInputStream = getClass().getResourceAsStream(vertexShader);
if (vertexShaderInputStream == null) {
throw new IOException("Could not find vertex shader file");
}
- InputStream fragmentShaderInputStream = getClass().getResourceAsStream("/shaders/plain.frag.glsl");
+ InputStream fragmentShaderInputStream = getClass().getResourceAsStream(fragmentShader);
if (fragmentShaderInputStream == null) {
throw new IOException("Could not find fragment shader file");
}
shaderProgramId = ShaderLoader.loadProgram(gl, IOUtils.toString(vertexShaderInputStream, StandardCharsets.UTF_8), IOUtils.toString(fragmentShaderInputStream, StandardCharsets.UTF_8));
- shaderVertexIndex = gl.glGetAttribLocation(shaderProgramId, "inPosition");
- shaderColorIndex = gl.glGetAttribLocation(shaderProgramId, "inColor");
+
+ gl.glBindAttribLocation(shaderProgramId, 0, "vertexPosition");
+ gl.glBindAttribLocation(shaderProgramId, 1, "vertexNormal");
+ gl.glBindAttribLocation(shaderProgramId, 2, "vertexColor");
} catch (IOException e) {
throw new GLException(e);
}
}
+ @Override
public int getShaderVertexIndex() {
- return shaderVertexIndex;
+ return 0;
+ }
+
+ @Override
+ public int getShaderNormalIndex() {
+ return 1;
}
+ @Override
public int getShaderColorIndex() {
- return shaderColorIndex;
+ return 3;
}
public void dispose(GL2 gl) {
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/Shader.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/Shader.java
index 2b2c5af795..d29be97092 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/Shader.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shader/Shader.java
@@ -45,4 +45,25 @@ public interface Shader {
* @return the id of the shader program
*/
int getProgramId();
+
+ /**
+ * Get the shader parameter index for vertices
+ *
+ * @return the index
+ */
+ int getShaderVertexIndex();
+
+ /**
+ * Get the shader parameter index for colors
+ *
+ * @return the index
+ */
+ int getShaderColorIndex();
+
+ /**
+ * Get the shader parameter index for normals
+ *
+ * @return the index
+ */
+ int getShaderNormalIndex();
}
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/GcodeRenderer.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/GcodeRenderer.java
index 13cd04b6ac..8801828b31 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/GcodeRenderer.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/GcodeRenderer.java
@@ -23,11 +23,8 @@ This file is part of Universal Gcode Sender (UGS).
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.JoglVersion;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW;
-import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION;
import com.jogamp.opengl.glu.GLU;
import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions;
-import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_BG;
import com.willwinder.ugs.nbm.visualizer.renderables.Grid;
import com.willwinder.ugs.nbm.visualizer.renderables.MachineBoundries;
import com.willwinder.ugs.nbm.visualizer.renderables.MouseOver;
@@ -56,6 +53,10 @@ This file is part of Universal Gcode Sender (UGS).
import java.util.logging.Level;
import java.util.logging.Logger;
+import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW;
+import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION;
+import static com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions.VISUALIZER_OPTION_BG;
+
/**
* 3D Canvas for GCode Visualizer
*
@@ -121,7 +122,7 @@ public class GcodeRenderer implements GLEventListener, IRenderableRegistrationSe
* Constructor.
*/
public GcodeRenderer() {
- eye = new Position(0, 0, 1.5);
+ eye = new Position(0, 0, 1.5);
center = new Position(0, 0, 0);
objectMin = new Position(-10, -10, -10);
objectMax = new Position(10, 10, 10);
@@ -239,18 +240,15 @@ public void init(GLAutoDrawable drawable) {
float[] diffuse = {.6f, .6f, .6f, 1.0f};
float[] position = {0f, 0f, 20f, 1.0f};
+ gl.glEnable(GL2.GL_LIGHT0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, ambient, 0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, diffuse, 0);
- gl.glEnable(GL2.GL_LIGHT0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, position, 0);
// Allow glColor to set colors
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glColorMaterial(GL.GL_FRONT, GL2.GL_DIFFUSE);
gl.glColorMaterial(GL.GL_FRONT, GL2.GL_AMBIENT);
- //gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL2.GL_AMBIENT_AND_DIFFUSE);
- //gl.glColorMaterial(GL.GL_FRONT, GL2.GL_SPECULAR);
-
float diffuseMaterial[] =
{0.5f, 0.5f, 0.5f, 1.0f};
@@ -469,7 +467,7 @@ private void initRenderables() {
objects.add(new MachineBoundries(Localization.getString("platform.visualizer.renderable.machine-boundries")));
objects.add(new Tool(Localization.getString("platform.visualizer.renderable.tool-location")));
objects.add(new MouseOver(Localization.getString("platform.visualizer.renderable.mouse-indicator")));
- objects.add(new OrientationCube(0.5f, Localization.getString("platform.visualizer.renderable.orientation-cube")));
+ objects.add(new OrientationCube(Localization.getString("platform.visualizer.renderable.orientation-cube")));
objects.add(new Grid(Localization.getString("platform.visualizer.renderable.grid")));
objects.add(new Plane(Localization.getString("platform.visualizer.renderable.grid")));
Collections.sort(objects);
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/VertexObjectRenderable.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/VertexObjectRenderable.java
index 3d3f34166c..3777d2593b 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/VertexObjectRenderable.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/shared/VertexObjectRenderable.java
@@ -3,46 +3,49 @@
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptions;
-import com.willwinder.ugs.nbm.visualizer.shader.PlainShader;
+import com.willwinder.ugs.nbm.visualizer.shader.Shader;
import com.willwinder.ugs.nbm.visualizer.utils.RenderableUtils;
-import static com.willwinder.ugs.nbm.visualizer.utils.RenderableUtils.bindColorBuffer;
-import static com.willwinder.ugs.nbm.visualizer.utils.RenderableUtils.bindVertexBuffer;
-import static com.willwinder.ugs.nbm.visualizer.utils.RenderableUtils.bindVertexObject;
import com.willwinder.universalgcodesender.model.Position;
import java.util.ArrayList;
import java.util.List;
+import static com.willwinder.ugs.nbm.visualizer.utils.RenderableUtils.*;
+
/**
* A base class for rendering a vertex buffer object using a shader
*/
public abstract class VertexObjectRenderable extends Renderable {
private double stepSize;
private final List vertexList = new ArrayList<>();
+ private final List normalList = new ArrayList<>();
private final List colorList = new ArrayList<>();
private Position objectMin = Position.ZERO;
private Position objectMax = Position.ZERO;
- private PlainShader shader;
+ private Shader shader;
private boolean reloadModel;
private int vertexObjectId;
private int vertexBufferId;
private int colorBufferId;
+ private int normalBufferId;
protected double getStepSize() {
return stepSize;
}
- protected VertexObjectRenderable(int priority, String title, String enabledOptionKey) {
+ protected VertexObjectRenderable(int priority, String title, String enabledOptionKey, Shader shader) {
super(priority, title, enabledOptionKey);
+ this.shader = shader;
reloadPreferences(new VisualizerOptions());
}
- private void clear() {
+ protected void clear() {
vertexList.clear();
colorList.clear();
+ normalList.clear();
}
@Override
@@ -55,6 +58,10 @@ public boolean center() {
return true;
}
+ protected void addNormal(double x, double y, double z) {
+ RenderableUtils.addVertex(normalList, x, y, z);
+ }
+
protected void addVertex(double x, double y, double z) {
RenderableUtils.addVertex(vertexList, x, y, z);
}
@@ -77,7 +84,6 @@ public void reloadPreferences(VisualizerOptions vo) {
@Override
public void init(GLAutoDrawable drawable) {
- shader = new PlainShader();
shader.init(drawable.getGL().getGL2());
}
@@ -117,8 +123,7 @@ public final void draw(GLAutoDrawable drawable, boolean idle, Position machineCo
// Bind the VAO containing the vertex data
gl.glBindVertexArray(vertexObjectId);
-
- render(gl);
+ render(drawable);
// Unbind the VAO
gl.glBindVertexArray(0);
@@ -127,18 +132,19 @@ public final void draw(GLAutoDrawable drawable, boolean idle, Position machineCo
private void updateBuffers(GL2 gl) {
- gl.glDeleteBuffers(2, new int[]{vertexBufferId, colorBufferId}, 0);
+ gl.glDeleteBuffers(2, new int[]{vertexBufferId, colorBufferId, normalBufferId}, 0);
vertexObjectId = bindVertexObject(gl);
vertexBufferId = bindVertexBuffer(gl, vertexList, shader.getShaderVertexIndex());
colorBufferId = bindColorBuffer(gl, colorList, shader.getShaderColorIndex());
+ normalBufferId = bindNormalBuffer(gl, normalList, shader.getShaderNormalIndex());
}
/**
* A method to be used for rendering the vertex buffer.
*
- * @param gl the current gl context
+ * @param drawable the current gl context
*/
- public abstract void render(GL2 gl);
+ public abstract void render(GLAutoDrawable drawable);
/**
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/RenderableUtils.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/RenderableUtils.java
index ab86d52a19..1c3f8b0888 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/RenderableUtils.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/RenderableUtils.java
@@ -53,6 +53,33 @@ public static int bindColorBuffer(GL2 gl, List colorList, int vertexBuffe
return cbo[0];
}
+ /**
+ * Generates and binds a color buffer
+ *
+ * @param gl the GL context to use
+ * @param normalList a list of float values containing the vertex normal
+ * @param normalBufferIndex the parameter index of the shader to bind to
+ * @return the id of the color buffer to be reference to when rendering
+ */
+ public static int bindNormalBuffer(GL2 gl, List normalList, int normalBufferIndex) {
+ // Create and upload the Normal Buffer Object (NBO) for colors
+ int[] nbo = new int[1];
+ gl.glGenBuffers(1, nbo, 0);
+
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, nbo[0]);
+
+ // Upload vertex colors to the GPU
+ FloatBuffer normalBuffer = Buffers.newDirectFloatBuffer(ArrayUtils.toPrimitive(normalList.toArray(new Float[0])));
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, normalBuffer.capacity() * Float.BYTES, normalBuffer, GL.GL_STATIC_DRAW);
+
+ // Specify vertex attribute layout (index 1 for color)
+ gl.glEnableVertexAttribArray(normalBufferIndex);
+ gl.glVertexAttribPointer(normalBufferIndex, 4, GL.GL_FLOAT, false, 4 * Float.BYTES, 0);
+
+ return nbo[0];
+ }
+
+
public static int bindVertexBuffer(GL2 gl, List vertexList, int positionIndex) {
// Create a Vertex Buffer Object (VBO)
int[] vbo = new int[1];
@@ -61,7 +88,7 @@ public static int bindVertexBuffer(GL2 gl, List vertexList, int positionI
// Send vertex data to the GPU
FloatBuffer vertexBuffer = Buffers.newDirectFloatBuffer(ArrayUtils.toPrimitive(vertexList.toArray(new Float[0])));
- gl.glBufferData(GL.GL_ARRAY_BUFFER, vertexBuffer.limit() * Float.BYTES, vertexBuffer, GL.GL_STATIC_DRAW);
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, vertexBuffer.capacity() * Float.BYTES, vertexBuffer, GL.GL_STATIC_DRAW);
// Specify the layout of the vertex data
gl.glEnableVertexAttribArray(positionIndex);
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/ShaderLoader.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/ShaderLoader.java
index 474066e2b7..c821736bdf 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/ShaderLoader.java
+++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/utils/ShaderLoader.java
@@ -108,6 +108,11 @@ public static int loadProgram(final GL2ES2 gl, final String vertexShaderSource,
throw new GLException(log);
}
+ // Explicitly bind the parameters locations
+ gl.glBindAttribLocation(program, 0, "gl_Position");
+ gl.glBindAttribLocation(program, 1, "gl_Normal");
+ gl.glBindAttribLocation(program, 3, "gl_Color");
+
// Clean up the shaders
gl.glDeleteShader(vertexShaderId);
gl.glDeleteShader(fragmentShaderId);
diff --git a/ugs-platform/ugs-platform-visualizer/src/main/resources/shaders/plain.vert.glsl b/ugs-platform/ugs-platform-visualizer/src/main/resources/shaders/plain.vert.glsl
index 3cf4459146..06d6aaa851 100644
--- a/ugs-platform/ugs-platform-visualizer/src/main/resources/shaders/plain.vert.glsl
+++ b/ugs-platform/ugs-platform-visualizer/src/main/resources/shaders/plain.vert.glsl
@@ -1,16 +1,12 @@
#version 110
-// Input vertex position and color
-attribute vec3 inPosition;
-attribute vec4 inColor;
-
// Output color to the fragment shader
varying vec4 fragColor;
void main() {
// Set the vertex position
- gl_Position = gl_ModelViewProjectionMatrix * vec4(inPosition, 1.0);
+ gl_Position = ftransform();
// Pass the vertex color to the fragment shader
- fragColor = inColor;
+ fragColor = gl_Color;
}
\ No newline at end of file