mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-15 21:05:22 +01:00
rename surface to plane
This commit is contained in:
parent
8f89af7beb
commit
25acb0ff6f
8 changed files with 125 additions and 115 deletions
112
src/cad/Cad.java
112
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
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public class AppCtrl implements Initializable {
|
|||
}
|
||||
|
||||
private void setInitObject(Group parent) {
|
||||
List<Surface> cube = Utils3D.createCube(100);
|
||||
List<Plane> cube = Utils3D.createCube(100);
|
||||
parent.getChildren().addAll(cadContext.toNodes(cube));
|
||||
//
|
||||
// CSG init = new Cube(100).toCSG().difference(new Cylinder(30, 100, 10).toCSG());
|
||||
|
|
|
|||
|
|
@ -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<Surface> polygons = new TIntObjectHashMap<>();
|
||||
public final TIntObjectMap<Plane> polygons = new TIntObjectHashMap<>();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Surface, Sketch> sketches = new HashMap<>();
|
||||
public final Map<Plane, Sketch> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Vector> polygon : sketch.polygons) {
|
||||
if (polygon.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Surface surface = new Surface(sketch.owner.normal, polygon, Collections.emptyList());
|
||||
List<Surface> extruded = Surface.extrude(surface, dir);
|
||||
Plane plane = new Plane(sketch.owner.normal, polygon, Collections.emptyList());
|
||||
List<Plane> 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<CSGNode> toNodes(List<Surface> extruded) {
|
||||
public List<CSGNode> toNodes(List<Plane> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Vector> shell;
|
||||
|
|
@ -23,15 +23,15 @@ public class Surface {
|
|||
|
||||
private List<Vector[]> triangles;
|
||||
|
||||
public Surface(List<Vector> shell) {
|
||||
public Plane(List<Vector> shell) {
|
||||
this(shell, Collections.emptyList());
|
||||
}
|
||||
|
||||
public Surface(List<Vector> shell, List<List<Vector>> holes) {
|
||||
public Plane(List<Vector> shell, List<List<Vector>> holes) {
|
||||
this(normalOfCCWSeq(shell.get(0), shell.get(1), shell.get(2)), shell, holes);
|
||||
}
|
||||
|
||||
public Surface(Vector normal, List<Vector> shell, List<List<Vector>> holes) {
|
||||
public Plane(Vector normal, List<Vector> shell, List<List<Vector>> 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<Vector> 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<Surface> extrude(Surface source, Vector target) {
|
||||
public static List<Plane> 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<Surface> surfaces = new ArrayList<>();
|
||||
surfaces.add(source);
|
||||
List<Plane> 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> T get(List<T> 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<Vector> shell = this.shell.stream().map(vector -> vector.plus(target)).collect(toList());
|
||||
List<List<Vector>> holes = new ArrayList<>();
|
||||
for (List<Vector> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,11 +8,11 @@ import java.util.List;
|
|||
|
||||
public class Sketch {
|
||||
|
||||
public final Surface owner;
|
||||
public final Plane owner;
|
||||
public final List<List<Vector>> polygons = new ArrayList<>();
|
||||
public final Group drawLayer = new Group();
|
||||
|
||||
public Sketch(Surface owner) {
|
||||
public Sketch(Plane owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Surface> surfaces) {
|
||||
public static CSGMesh getMesh(List<Plane> 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<Surface> createCube(double width) {
|
||||
Surface square = createSquare(width);
|
||||
return Surface.extrude(square, square.normal.scale(width));
|
||||
public static List<Plane> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue