mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-09 18:02:50 +01:00
surface selection
This commit is contained in:
parent
29202bfa69
commit
435dd9f02c
4 changed files with 197 additions and 49 deletions
|
|
@ -3,10 +3,12 @@ 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 {
|
||||
|
|
@ -17,6 +19,12 @@ public class CSGNode extends MeshView {
|
|||
super(mesh);
|
||||
this.context = context;
|
||||
setMaterial(Utils3D.DEFAULT_MATERIAL);
|
||||
setOnMouseEntered(e -> {
|
||||
context.highlightManger.selectExclusively(this);
|
||||
});
|
||||
setOnMouseExited(e -> {
|
||||
context.highlightManger.getSelection().clear();
|
||||
});
|
||||
setOnMouseClicked(e -> {
|
||||
context.clickOnNode(this, e);
|
||||
});
|
||||
|
|
@ -25,6 +33,10 @@ public class CSGNode extends MeshView {
|
|||
private void highlight(Polygon poly) {
|
||||
System.out.println(poly);
|
||||
}
|
||||
|
||||
private void select(Polygon poly) {
|
||||
System.out.println(poly);
|
||||
}
|
||||
|
||||
public final Map<Surface, Sketch> sketches = new HashMap<>();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
package cad.fx;
|
||||
|
||||
import cad.math.Vector;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.input.PickResult;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.MeshView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -11,8 +15,58 @@ public class CadContext {
|
|||
|
||||
public Sketcher sketcher;
|
||||
public Selection selection;
|
||||
public final SelectionManager selectionManger = new SelectionManager();
|
||||
public final SelectionManager highlightManger = new SelectionManager();
|
||||
|
||||
|
||||
class MaterialChangeListener implements SelectionManager.Listener {
|
||||
|
||||
public final PhongMaterial onSelect;
|
||||
public final PhongMaterial onDeselect;
|
||||
private SelectionManager dependency;
|
||||
|
||||
MaterialChangeListener(PhongMaterial onSelect, PhongMaterial onDeselect, SelectionManager dependency) {
|
||||
this.onSelect = onSelect;
|
||||
this.onDeselect = onDeselect;
|
||||
this.dependency = dependency;
|
||||
}
|
||||
|
||||
public void added(List<Node> nodes) {
|
||||
if (dependency != null) {
|
||||
nodes = filter(nodes, dependency);
|
||||
}
|
||||
setMaterial(nodes, onSelect);
|
||||
}
|
||||
|
||||
public void removed(List<Node> nodes) {
|
||||
if (dependency != null) {
|
||||
nodes = filter(nodes, dependency);
|
||||
}
|
||||
setMaterial(nodes, onDeselect);
|
||||
}
|
||||
|
||||
private List<Node> filter(List<Node> nodes, SelectionManager dependency) {
|
||||
nodes = new ArrayList<>(nodes);
|
||||
nodes.removeAll(selectionManger.getSelection());
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
selectionManger.addListener(new MaterialChangeListener(Utils3D.SELECTED_MATERIAL, Utils3D.DEFAULT_MATERIAL, null));
|
||||
highlightManger.addListener(new MaterialChangeListener(Utils3D.HIGHLIGHTED_MATERIAL, Utils3D.DEFAULT_MATERIAL, selectionManger));
|
||||
}
|
||||
|
||||
private void setMaterial(List<Node> nodes, PhongMaterial material) {
|
||||
for (Node node : nodes) {
|
||||
if (node instanceof MeshView) {
|
||||
((MeshView) node).setMaterial(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clickOnNode(CSGNode csgNode, MouseEvent e) {
|
||||
selectionManger.selectExclusively(csgNode);
|
||||
PickResult pickResult = e.getPickResult();
|
||||
int face = pickResult.getIntersectedFace();
|
||||
CSGMesh csgMesh = (CSGMesh) csgNode.getMesh();
|
||||
|
|
@ -64,8 +118,10 @@ public class CadContext {
|
|||
|
||||
Surface surface = new Surface(sketch.owner.normal, polygon, Collections.emptyList());
|
||||
List<Surface> extruded = Surface.extrude(surface, dir);
|
||||
sketch.drawLayer.getChildren().addAll(new CSGNode(Utils3D.getMesh(extruded), this)); // fixme
|
||||
|
||||
for (Surface s : extruded) {
|
||||
sketch.drawLayer.getChildren().addAll(new CSGNode( Utils3D.getMesh(Collections.singletonList(s)), this)); // fixme
|
||||
}
|
||||
// CSG pad = Extrude.points(dir, polygon);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
66
src/cad/fx/SelectionManager.java
Normal file
66
src/cad/fx/SelectionManager.java
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
package cad.fx;
|
||||
|
||||
import com.sun.javafx.collections.TrackableObservableList;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.Node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SelectionManager {
|
||||
|
||||
private final List<Listener> listeners = new ArrayList<>();
|
||||
|
||||
public void addListener(Listener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
private final ObservableList<Node> selection = new TrackableObservableList<Node>() {
|
||||
|
||||
protected void onChanged(ListChangeListener.Change<Node> c) {
|
||||
while (c.next()) {
|
||||
if (c.wasAdded()) {
|
||||
List<Node> added = c.getAddedSubList();
|
||||
added.forEach((n) -> {
|
||||
ObservableList<String> styleClass = n.getStyleClass();
|
||||
if (!styleClass.contains("selected")) {
|
||||
styleClass.add("selected");
|
||||
}
|
||||
});
|
||||
fireSelected(added);
|
||||
} else if (c.wasRemoved()) {
|
||||
List<Node> removed = c.getRemoved();
|
||||
removed.forEach((n) -> n.getStyleClass().removeAll("selected"));
|
||||
fireRemoved(removed);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void fireRemoved(List<Node> removed) {
|
||||
for (Listener l : listeners) {
|
||||
l.removed(removed);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireSelected(List<Node> added) {
|
||||
for (Listener l : listeners) {
|
||||
l.added(added);
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableList<Node> getSelection() {
|
||||
return selection;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void added(List<Node> nodes);
|
||||
void removed(List<Node> nodes);
|
||||
}
|
||||
|
||||
public void selectExclusively(Node node) {
|
||||
selection.clear();
|
||||
selection.add(node);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,17 +22,26 @@ import java.util.List;
|
|||
public class Utils3D {
|
||||
|
||||
public static final PhongMaterial DEFAULT_MATERIAL = new PhongMaterial();
|
||||
public static final PhongMaterial SELECTED_MATERIAL = new PhongMaterial();
|
||||
public static final PhongMaterial HIGHLIGHTED_MATERIAL = new PhongMaterial();
|
||||
|
||||
static {
|
||||
// DEFAULT_MATERIAL.setDiffuseColor(Color.LIGHTBLUE);
|
||||
// DEFAULT_MATERIAL.setSpecularColor(Color.WHITE);
|
||||
|
||||
DEFAULT_MATERIAL.setDiffuseColor(Color.LIGHTSTEELBLUE);
|
||||
DEFAULT_MATERIAL.setSpecularColor(Color.LIGHTBLUE);
|
||||
// DEFAULT_MATERIAL.setSpecularColor(Color.LIGHTBLUE);
|
||||
|
||||
SELECTED_MATERIAL.setDiffuseColor(Color.LIGHTSEAGREEN);
|
||||
// SELECTED_MATERIAL.setSpecularColor(Color.SEAGREEN); //disable reflection
|
||||
|
||||
HIGHLIGHTED_MATERIAL.setDiffuseColor(Color.LIGHTGOLDENRODYELLOW);
|
||||
// HIGHLIGHTED_MATERIAL.setSpecularColor(Color.GOLD);
|
||||
|
||||
// DEFAULT_MATERIAL.setDiffuseMap(new Image(Utils3D.class.getResource("tex.png").toExternalForm()));
|
||||
}
|
||||
|
||||
|
||||
public static CSGMesh getMesh(List<Surface> surfaces) {
|
||||
|
||||
CSGMesh mesh = new CSGMesh();
|
||||
|
|
@ -45,46 +54,46 @@ public class Utils3D {
|
|||
for (Vector[] triangle : surface.getTriangles()) {
|
||||
|
||||
|
||||
mesh.getPoints().addAll(
|
||||
(float) triangle[0].x,
|
||||
(float) triangle[0].y,
|
||||
(float) triangle[0].z
|
||||
);
|
||||
mesh.getPoints().addAll(
|
||||
(float) triangle[0].x,
|
||||
(float) triangle[0].y,
|
||||
(float) triangle[0].z
|
||||
);
|
||||
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
|
||||
|
||||
mesh.getPoints().addAll(
|
||||
(float) triangle[1].x,
|
||||
(float) triangle[1].y,
|
||||
(float) triangle[1].z
|
||||
(float) triangle[1].x,
|
||||
(float) triangle[1].y,
|
||||
(float) triangle[1].z
|
||||
);
|
||||
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
|
||||
mesh.getPoints().addAll(
|
||||
(float) triangle[2].x,
|
||||
(float) triangle[2].y,
|
||||
(float) triangle[2].z
|
||||
(float) triangle[2].x,
|
||||
(float) triangle[2].y,
|
||||
(float) triangle[2].z
|
||||
);
|
||||
|
||||
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
|
||||
int counter = faceCounter * 3;
|
||||
mesh.getFaces().addAll(
|
||||
counter, // first vertex
|
||||
0, // texture (not covered)
|
||||
counter + 1, // second vertex
|
||||
0, // texture (not covered)
|
||||
counter + 2, // third vertex
|
||||
0 // texture (not covered)
|
||||
);
|
||||
mesh.polygons.put(faceCounter, surface);
|
||||
++faceCounter;
|
||||
int counter = faceCounter * 3;
|
||||
mesh.getFaces().addAll(
|
||||
counter, // first vertex
|
||||
0, // texture (not covered)
|
||||
counter + 1, // second vertex
|
||||
0, // texture (not covered)
|
||||
counter + 2, // third vertex
|
||||
0 // texture (not covered)
|
||||
);
|
||||
mesh.polygons.put(faceCounter, surface);
|
||||
++faceCounter;
|
||||
|
||||
} // end if #verts >= 3
|
||||
|
||||
|
|
@ -105,27 +114,27 @@ public class Utils3D {
|
|||
TriangulationPoint firstVertex = p.points[0];
|
||||
|
||||
mesh.getPoints().addAll(
|
||||
p.points[2].getXf(),
|
||||
p.points[2].getYf(),
|
||||
p.points[2].getZf()
|
||||
p.points[2].getXf(),
|
||||
p.points[2].getYf(),
|
||||
p.points[2].getZf()
|
||||
);
|
||||
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
|
||||
mesh.getPoints().addAll(
|
||||
p.points[1].getXf(),
|
||||
p.points[1].getYf(),
|
||||
p.points[1].getZf()
|
||||
p.points[1].getXf(),
|
||||
p.points[1].getYf(),
|
||||
p.points[1].getZf()
|
||||
);
|
||||
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
mesh.getTexCoords().addAll(0);
|
||||
|
||||
mesh.getPoints().addAll(
|
||||
p.points[0].getXf(),
|
||||
p.points[0].getYf(),
|
||||
p.points[0].getZf()
|
||||
p.points[0].getXf(),
|
||||
p.points[0].getYf(),
|
||||
p.points[0].getZf()
|
||||
);
|
||||
|
||||
mesh.getTexCoords().addAll(0); // texture (not covered)
|
||||
|
|
@ -133,12 +142,12 @@ public class Utils3D {
|
|||
|
||||
int counter = faceCounter * 3;
|
||||
mesh.getFaces().addAll(
|
||||
counter, // first vertex
|
||||
0, // texture (not covered)
|
||||
counter + 1, // second vertex
|
||||
0, // texture (not covered)
|
||||
counter + 2, // third vertex
|
||||
0 // texture (not covered)
|
||||
counter, // first vertex
|
||||
0, // texture (not covered)
|
||||
counter + 1, // second vertex
|
||||
0, // texture (not covered)
|
||||
counter + 2, // third vertex
|
||||
0 // texture (not covered)
|
||||
);
|
||||
// mesh.polygons.put(faceCounter, p);
|
||||
++faceCounter;
|
||||
|
|
@ -148,15 +157,20 @@ 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 Surface createSquare(double width) {
|
||||
|
||||
width /= 2;
|
||||
|
||||
List<Vector> shell = Arrays.asList(
|
||||
new Vector(-width, -width),
|
||||
new Vector(width, -width),
|
||||
new Vector(width, width, 0),
|
||||
new Vector(-width, width, 0)
|
||||
new Vector(-width, -width),
|
||||
new Vector(width, -width),
|
||||
new Vector(width, width, 0),
|
||||
new Vector(-width, width, 0)
|
||||
);
|
||||
|
||||
// width /= 3;
|
||||
|
|
|
|||
Loading…
Reference in a new issue