diff --git a/src/cad/Cad.java b/src/cad/Cad.java index bd2858ee..894fd56c 100644 --- a/src/cad/Cad.java +++ b/src/cad/Cad.java @@ -1,19 +1,16 @@ package cad; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.FPSAnimator; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; -import javax.media.opengl.awt.AWTGLAutoDrawable; -import javax.media.opengl.awt.GLJPanel; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; +import javax.media.opengl.Threading; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener { @@ -24,7 +21,9 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener private static GLWindow window; - public static void main(String[] args) { + ExecutorService updater = Executors.newSingleThreadExecutor(); + + public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException { // Get the default OpenGL profile, reflecting the best for your running platform GLProfile glp = GLProfile.getDefault(); @@ -34,42 +33,41 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener window = GLWindow.create(caps); // Create a animator that drives canvas' display() at the specified FPS. - final FPSAnimator animator = new FPSAnimator(window, 60, true); +// final FPSAnimator animator = new FPSAnimator(window, 60, true); //// final Animator animator = new Animator(window); - window.addWindowListener(new com.jogamp.newt.event.WindowAdapter() { - @Override - public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent arg0) { - // Use a dedicate thread to run the stop() to ensure that the - // animator stops before program exits. - new Thread() { - @Override - public void run() { - if (animator.isStarted()) - animator.stop(); // stop the animator loop - } - }.start(); - } - }); +// window.addWindowListener(new com.jogamp.newt.event.WindowAdapter() { +// @Override +// public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent arg0) { +// // Use a dedicate thread to run the stop() to ensure that the +// // animator stops before program exits. +// new Thread() { +// @Override +// public void run() { +// if (animator.isStarted()) +// animator.stop(); // stop the animator loop +// } +// }.start(); +// } +// }); window.addGLEventListener(new Cad()); window.setSize(640, 480); window.setTitle("CAD"); window.setVisible(true); - - - new Thread(new Runnable() { - public void run() { - final Object monitor = new Object(); - synchronized (monitor) { - while (true) - try { + + Executors.newSingleThreadExecutor().execute(() -> { + Object monitor = new Object(); + while (true) { + try { + synchronized (monitor) { monitor.wait(); - } catch (InterruptedException e) { } + } catch (InterruptedException e) { } } - }).start(); + }); + // animator.start(); } @@ -143,20 +141,15 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener public void display(GLAutoDrawable drawable) { // Turn the gears' teeth - angle += 2.0f; +// angle += 2.0f; // Get the GL corresponding to the drawable we are animating GL2 gl = drawable.getGL().getGL2(); // Special handling for the case where the GLJPanel is translucent // and wants to be composited with other Java 2D content - if ((drawable instanceof GLJPanel) && - !((GLJPanel) drawable).isOpaque() && - ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { - gl.glClear(GL2.GL_DEPTH_BUFFER_BIT); - } else { - gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); - } + + gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); // Rotate the entire assembly of gears based on how the user // dragged the mouse around @@ -167,7 +160,7 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener // Place the first gear and call its display list gl.glPushMatrix(); - gl.glTranslatef(-3.0f, -2.0f, 0.0f); + gl.glTranslatef(1.0f, 1.0f, 0.0f); gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); gl.glCallList(gear1); gl.glPopMatrix(); @@ -339,6 +332,41 @@ public class Cad implements GLEventListener, com.jogamp.newt.event.MouseListener view_rotx += thetaX; view_roty += thetaY; + + update(window::display); + } + + + + volatile boolean updating = false; + + private void update(Runnable op) { + if (updating) { + return; + } + + Threading.invokeOnOpenGLThread(false, new Runnable() { + @Override + public void run() { + try { + updating = true; + + op.run(); + } finally { + updating = false; + } + } + }); + +// updater.execute(() -> { +// try { +// updating = true; +// +// op.run(); +// } finally { +// updating = false; +// } +// }); } @Override diff --git a/src/cad/fx/AppCtrl.java b/src/cad/fx/AppCtrl.java index 45317eaa..d862ec0d 100644 --- a/src/cad/fx/AppCtrl.java +++ b/src/cad/fx/AppCtrl.java @@ -36,7 +36,7 @@ public class AppCtrl implements Initializable { } private void setInitObject(Group parent) { - List cube = Utils3D.createCube(100); + List cube = Utils3D.createCube(100); parent.getChildren().addAll(cadContext.toNodes(cube)); // // CSG init = new Cube(100).toCSG().difference(new Cylinder(30, 100, 10).toCSG()); diff --git a/src/cad/fx/CSGMesh.java b/src/cad/fx/CSGMesh.java index 6180fc7e..5edfc12b 100644 --- a/src/cad/fx/CSGMesh.java +++ b/src/cad/fx/CSGMesh.java @@ -1,12 +1,11 @@ package cad.fx; -import eu.mihosoft.vrl.v3d.Polygon; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import javafx.scene.shape.TriangleMesh; public class CSGMesh extends TriangleMesh { - public final TIntObjectMap polygons = new TIntObjectHashMap<>(); + public final TIntObjectMap polygons = new TIntObjectHashMap<>(); } diff --git a/src/cad/fx/CSGNode.java b/src/cad/fx/CSGNode.java index 2687e2cf..7f312cbf 100644 --- a/src/cad/fx/CSGNode.java +++ b/src/cad/fx/CSGNode.java @@ -1,14 +1,10 @@ package cad.fx; -import eu.mihosoft.vrl.v3d.CSG; import eu.mihosoft.vrl.v3d.Polygon; import javafx.scene.Group; -import javafx.scene.Node; -import javafx.scene.Parent; import javafx.scene.shape.MeshView; import java.util.HashMap; -import java.util.List; import java.util.Map; public class CSGNode extends MeshView { @@ -38,14 +34,14 @@ public class CSGNode extends MeshView { System.out.println(poly); } - public final Map sketches = new HashMap<>(); + public final Map sketches = new HashMap<>(); - public Sketch getSketch(Surface surface) { - Sketch sketch = sketches.get(surface); + public Sketch getSketch(Plane plane) { + Sketch sketch = sketches.get(plane); if (sketch == null) { - sketch = new Sketch(surface); + sketch = new Sketch(plane); ((Group) getParent()).getChildren().add(sketch.drawLayer); - sketches.put(surface, sketch); + sketches.put(plane, sketch); } return sketch; } diff --git a/src/cad/fx/CadContext.java b/src/cad/fx/CadContext.java index 893188ab..5173b81b 100644 --- a/src/cad/fx/CadContext.java +++ b/src/cad/fx/CadContext.java @@ -10,9 +10,6 @@ import javafx.scene.shape.MeshView; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collector; -import java.util.stream.Collectors; -import java.util.stream.Stream; import static java.util.stream.Collectors.toList; @@ -75,20 +72,20 @@ public class CadContext { PickResult pickResult = e.getPickResult(); int face = pickResult.getIntersectedFace(); CSGMesh csgMesh = (CSGMesh) csgNode.getMesh(); - Surface surface = csgMesh.polygons.get(face); - System.out.println(surface); - if (surface != null) { + Plane plane = csgMesh.polygons.get(face); + System.out.println(plane); + if (plane != null) { if (selection != null) { - boolean isSameNode = selection.sameTo(csgNode, surface); + boolean isSameNode = selection.sameTo(csgNode, plane); if (sketcher == null && !isSameNode) { - selection = new Selection(csgNode, surface); + selection = new Selection(csgNode, plane); } if (sketcher != null && isSameNode) { sketcher.addPoint(pickResult.getIntersectedPoint()); } } else { if (sketcher == null) { - selection = new Selection(csgNode, surface); + selection = new Selection(csgNode, plane); } } } @@ -98,7 +95,7 @@ public class CadContext { if (sketcher != null || selection == null) { return; } - sketcher = new Sketcher(selection.csgNode.getSketch(selection.surface)); + sketcher = new Sketcher(selection.csgNode.getSketch(selection.plane)); } public void endSketching() { @@ -114,43 +111,43 @@ public class CadContext { return; } - Sketch sketch = selection.csgNode.getSketch(selection.surface); + Sketch sketch = selection.csgNode.getSketch(selection.plane); Vector dir = sketch.owner.normal.scale(height); for (List polygon : sketch.polygons) { if (polygon.isEmpty()) { continue; } - Surface surface = new Surface(sketch.owner.normal, polygon, Collections.emptyList()); - List extruded = Surface.extrude(surface, dir); + Plane plane = new Plane(sketch.owner.normal, polygon, Collections.emptyList()); + List extruded = Plane.extrude(plane, dir); - for (Surface s : extruded) { + for (Plane s : extruded) { sketch.drawLayer.getChildren().addAll(toNodes(extruded));// fixme } // CSG pad = Extrude.points(dir, polygon); } } - public List toNodes(List extruded) { + public List toNodes(List extruded) { return extruded.stream().map(this::toNode).collect(toList()); } - public CSGNode toNode(Surface surface) { - return new CSGNode(Utils3D.getMesh(Collections.singletonList(surface)), this); + public CSGNode toNode(Plane plane) { + return new CSGNode(Utils3D.getMesh(Collections.singletonList(plane)), this); } public static class Selection { public final CSGNode csgNode; - public final Surface surface; + public final Plane plane; - public Selection(CSGNode csgNode, Surface surface) { + public Selection(CSGNode csgNode, Plane plane) { this.csgNode = csgNode; - this.surface = surface; + this.plane = plane; } - public boolean sameTo(CSGNode csgNode, Surface surface) { - return this.csgNode.equals(csgNode) && this.surface.equals(surface); + public boolean sameTo(CSGNode csgNode, Plane plane) { + return this.csgNode.equals(csgNode) && this.plane.equals(plane); } } } diff --git a/src/cad/fx/Surface.java b/src/cad/fx/Plane.java similarity index 85% rename from src/cad/fx/Surface.java rename to src/cad/fx/Plane.java index ceebf9f1..21350b3b 100644 --- a/src/cad/fx/Surface.java +++ b/src/cad/fx/Plane.java @@ -15,7 +15,7 @@ import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; -public class Surface { +public class Plane { public final Vector normal; public final List shell; @@ -23,15 +23,15 @@ public class Surface { private List triangles; - public Surface(List shell) { + public Plane(List shell) { this(shell, Collections.emptyList()); } - public Surface(List shell, List> holes) { + public Plane(List shell, List> holes) { this(normalOfCCWSeq(shell.get(0), shell.get(1), shell.get(2)), shell, holes); } - public Surface(Vector normal, List shell, List> holes) { + public Plane(Vector normal, List shell, List> holes) { this.normal = normal.normalize(); this.shell = shell; this.holes = holes; @@ -43,11 +43,11 @@ public class Surface { } } - public Surface fixCCW() { + public Plane fixCCW() { if (!normal.slightlyEqualTo(normalOfCCWSeq(shell.get(0), shell.get(1), shell.get(2)))) { List shell = new ArrayList<>(this.shell); Collections.reverse(shell); - return new Surface(normal, shell, holes); + return new Plane(normal, shell, holes); } return this; } @@ -128,11 +128,11 @@ public class Surface { triangle[2] = first; } - public Surface flip() { - return new Surface(normal.negate(), shell, holes); + public Plane flip() { + return new Plane(normal.negate(), shell, holes); } - public static List extrude(Surface source, Vector target) { + public static List extrude(Plane source, Vector target) { double dotProduct = target.normalize().dot(source.normal); if (dotProduct == 0) { @@ -143,22 +143,22 @@ public class Surface { } source = source.fixCCW(); - List surfaces = new ArrayList<>(); - surfaces.add(source); + List planes = new ArrayList<>(); + planes.add(source); - Surface lid = source.shift(target).flip(); - surfaces.add(lid); + Plane lid = source.shift(target).flip(); + planes.add(lid); for (int i = 0; i < source.shell.size(); i++) { - Surface face = new Surface(Arrays.asList( + Plane face = new Plane(Arrays.asList( get(source.shell, i - 1), get(lid.shell, i - 1), get(lid.shell, i), get(source.shell, i) )); - surfaces.add(face); + planes.add(face); } - return surfaces; + return planes; } private static T get(List list, int i) { @@ -169,12 +169,12 @@ public class Surface { return list.get(i); } - public Surface shift(Vector target) { + public Plane shift(Vector target) { List shell = this.shell.stream().map(vector -> vector.plus(target)).collect(toList()); List> holes = new ArrayList<>(); for (List hole : this.holes) { holes.add(hole.stream().map(vector -> vector.plus(target)).collect(toList())); } - return new Surface(normal, shell, holes); + return new Plane(normal, shell, holes); } } diff --git a/src/cad/fx/Sketch.java b/src/cad/fx/Sketch.java index a0eba62a..2ad2c399 100644 --- a/src/cad/fx/Sketch.java +++ b/src/cad/fx/Sketch.java @@ -8,11 +8,11 @@ import java.util.List; public class Sketch { - public final Surface owner; + public final Plane owner; public final List> polygons = new ArrayList<>(); public final Group drawLayer = new Group(); - public Sketch(Surface owner) { + public Sketch(Plane owner) { this.owner = owner; } } diff --git a/src/cad/fx/Utils3D.java b/src/cad/fx/Utils3D.java index 13cfa408..fd1fcf63 100644 --- a/src/cad/fx/Utils3D.java +++ b/src/cad/fx/Utils3D.java @@ -1,18 +1,8 @@ package cad.fx; import cad.math.Vector; -import eu.mihosoft.vrl.v3d.CSG; -import eu.mihosoft.vrl.v3d.MeshContainer; -import eu.mihosoft.vrl.v3d.Polygon; -import eu.mihosoft.vrl.v3d.Vector3d; -import eu.mihosoft.vrl.v3d.Vertex; -import eu.mihosoft.vrl.v3d.ext.org.poly2tri.PolygonUtil; -import javafx.scene.image.Image; import javafx.scene.paint.Color; import javafx.scene.paint.PhongMaterial; -import javafx.scene.shape.TriangleMesh; -import org.poly2tri.Poly2Tri; -import org.poly2tri.geometry.polygon.PolygonPoint; import org.poly2tri.triangulation.TriangulationPoint; import org.poly2tri.triangulation.delaunay.DelaunayTriangle; @@ -42,16 +32,16 @@ public class Utils3D { } - public static CSGMesh getMesh(List surfaces) { + public static CSGMesh getMesh(List planes) { CSGMesh mesh = new CSGMesh(); int faceCounter = 0; - for (Surface surface : surfaces) { + for (Plane plane : planes) { - for (Vector[] triangle : surface.getTriangles()) { + for (Vector[] triangle : plane.getTriangles()) { mesh.getPoints().addAll( @@ -92,7 +82,7 @@ public class Utils3D { counter + 2, // third vertex 0 // texture (not covered) ); - mesh.polygons.put(faceCounter, surface); + mesh.polygons.put(faceCounter, plane); ++faceCounter; } // end if #verts >= 3 @@ -157,12 +147,12 @@ public class Utils3D { return mesh; } - public static List createCube(double width) { - Surface square = createSquare(width); - return Surface.extrude(square, square.normal.scale(width)); + public static List createCube(double width) { + Plane square = createSquare(width); + return Plane.extrude(square, square.normal.scale(width)); } - public static Surface createSquare(double width) { + public static Plane createSquare(double width) { width /= 2; @@ -183,6 +173,6 @@ public class Utils3D { // // polygon.addHole(hole); - return new Surface(shell); + return new Plane(shell); } }