Commit 913a2941 authored by Matthias Betz's avatar Matthias Betz
Browse files

Mount GLViewport in MainWindow and rewire Renderer to SceneData



Co-Authored-By: default avatarClaude Opus 4.8 <noreply@anthropic.com>
parent 419243a7
...@@ -130,7 +130,7 @@ public class CityDoctorController { ...@@ -130,7 +130,7 @@ public class CityDoctorController {
mainWindow.getOpenBtn().setDisable(true); mainWindow.getOpenBtn().setDisable(true);
mainWindow.getWriteReportButton().setDisable(true); mainWindow.getWriteReportButton().setDisable(true);
mainWindow.getMeshGroup().getChildren().clear(); mainWindow.clearMeshView();
clearTrees(); clearTrees();
mainWindow.resetSearchBar(); mainWindow.resetSearchBar();
...@@ -1660,7 +1660,7 @@ public class CityDoctorController { ...@@ -1660,7 +1660,7 @@ public class CityDoctorController {
} }
public void errorFilterIndexChanged(Number newV) { public void errorFilterIndexChanged(Number newV) {
mainWindow.getMeshGroup().getChildren().clear(); mainWindow.clearMeshView();
mainWindow.unselectEverything(); mainWindow.unselectEverything();
mainWindow.resetSearchBar(); mainWindow.resetSearchBar();
renderer.clearCurrentRender(); renderer.clearCurrentRender();
......
...@@ -31,9 +31,11 @@ import javafx.scene.layout.BorderPane; ...@@ -31,9 +31,11 @@ import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority; import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage; import javafx.stage.Stage;
import de.hft.stuttgart.citydoctor2.gui.gl.GLViewport;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -49,10 +51,6 @@ public class MainWindow extends Application { ...@@ -49,10 +51,6 @@ public class MainWindow extends Application {
private static final Logger logger = LogManager.getLogger(MainWindow.class); private static final Logger logger = LogManager.getLogger(MainWindow.class);
private static final double CAMERA_TRANSLATE_Z = -100.0;
private static final double CAMERA_INITIAL_X_ANGLE = 20.0;
private static final double CAMERA_INITIAL_Y_ANGLE = 120.0;
@FXML @FXML
private TreeView<Renderable> buildingsView; private TreeView<Renderable> buildingsView;
...@@ -214,19 +212,8 @@ public class MainWindow extends Application { ...@@ -214,19 +212,8 @@ public class MainWindow extends Application {
private Image north; private Image north;
private Image northFlip; private Image northFlip;
private Group meshGroup; private GLViewport glViewport;
private Group world;
private PerspectiveCamera camera;
private Rotate cameraXRotation = new Rotate();
private Rotate cameraZRotation = new Rotate();
private double dragX;
private double dragY;
private double cameraXRot = CAMERA_INITIAL_X_ANGLE;
private double cameraYRot = CAMERA_INITIAL_Y_ANGLE;
private double translateZ = CAMERA_TRANSLATE_Z;
private double[] clickStart = new double[2]; private double[] clickStart = new double[2];
@FXML @FXML
...@@ -245,7 +232,6 @@ public class MainWindow extends Application { ...@@ -245,7 +232,6 @@ public class MainWindow extends Application {
private FeatureType selectedTab = FeatureType.BUILDING; private FeatureType selectedTab = FeatureType.BUILDING;
private MainToolBar mainToolBar; private MainToolBar mainToolBar;
private SubScene geomScene;
private ImageView northArrow; private ImageView northArrow;
private static boolean loadFileAtStartup = false; private static boolean loadFileAtStartup = false;
...@@ -302,7 +288,7 @@ public class MainWindow extends Application { ...@@ -302,7 +288,7 @@ public class MainWindow extends Application {
FXMLLoader loader = new FXMLLoader(MainWindow.class.getResource("MainWindow.fxml")); FXMLLoader loader = new FXMLLoader(MainWindow.class.getResource("MainWindow.fxml"));
loader.setController(this); loader.setController(this);
BorderPane bp = loader.load(); BorderPane bp = loader.load();
highlightController = new HighlightController(world); highlightController = new HighlightController(glViewport);
renderer = new Renderer(this, highlightController); renderer = new Renderer(this, highlightController);
clickHandler = new VertexClickHandler(errorView, renderer, stage, this); clickHandler = new VertexClickHandler(errorView, renderer, stage, this);
controller = new CityDoctorController(this, highlightController, renderer); controller = new CityDoctorController(this, highlightController, renderer);
...@@ -845,36 +831,31 @@ public class MainWindow extends Application { ...@@ -845,36 +831,31 @@ public class MainWindow extends Application {
} }
private void setup3dView() { private void setup3dView() {
Group root = new Group(); glViewport = new GLViewport();
geomScene = new SubScene(root, 500, 300, true, SceneAntialiasing.BALANCED); Region canvas = glViewport.getNode();
geomScene.heightProperty().bind(meshView.heightProperty()); canvas.prefWidthProperty().bind(meshView.widthProperty());
geomScene.widthProperty().bind(meshView.widthProperty()); canvas.prefHeightProperty().bind(meshView.heightProperty());
geomScene.setFill(Color.AZURE); meshView.getChildren().add(canvas);
meshView.getChildren().add(geomScene);
canvas.addEventFilter(MouseEvent.MOUSE_PRESSED, me -> {
geomScene.addEventFilter(MouseEvent.MOUSE_PRESSED, me -> {
clickStart[0] = me.getScreenX(); clickStart[0] = me.getScreenX();
clickStart[1] = me.getScreenY(); clickStart[1] = me.getScreenY();
}); });
geomScene.addEventFilter(MouseEvent.MOUSE_RELEASED, me -> { canvas.addEventFilter(MouseEvent.MOUSE_RELEASED, me -> {
if (Math.abs(clickStart[0] - me.getScreenX()) > 3 || Math.abs(clickStart[1] - me.getScreenY()) > 3) { if (Math.abs(clickStart[0] - me.getScreenX()) > 3 || Math.abs(clickStart[1] - me.getScreenY()) > 3) {
// skip when mouse moved too much // skip when mouse moved too much
return; return;
} }
Node node = me.getPickResult().getIntersectedNode(); glViewport.requestPick(me.getX(), me.getY(), target -> {
if (node != null) { if (target instanceof Polygon p) {
Object o = node.getUserData(); new PolygonClickDispatcher(p).click(me, clickHandler);
if (o instanceof ClickDispatcher cd) {
cd.click(me, clickHandler);
}
} }
}); });
});
world = new Group(); // keep the north arrow aligned with the camera after orbit drags
root.getChildren().add(world); canvas.addEventFilter(MouseEvent.MOUSE_DRAGGED, me -> alignNorthArrow());
meshGroup = new Group();
world.getChildren().add(meshGroup);
north = new Image(getClass().getResourceAsStream("icons/north.png"), 50, 50, true, true); north = new Image(getClass().getResourceAsStream("icons/north.png"), 50, 50, true, true);
northFlip = new Image(getClass().getResourceAsStream("icons/north_flip.png"), 50, 50, true, true); northFlip = new Image(getClass().getResourceAsStream("icons/north_flip.png"), 50, 50, true, true);
...@@ -885,81 +866,13 @@ public class MainWindow extends Application { ...@@ -885,81 +866,13 @@ public class MainWindow extends Application {
northArrow.setY(10); northArrow.setY(10);
meshView.getChildren().add(northArrow); meshView.getChildren().add(northArrow);
northArrow.setVisible(false); northArrow.setVisible(false);
AmbientLight al = new AmbientLight(Color.WHITE);
root.getChildren().add(al);
buildCamera();
cameraXRotation.setAxis(Rotate.X_AXIS);
cameraZRotation.setAxis(Rotate.Z_AXIS);
world.getTransforms().add(cameraXRotation);
world.getTransforms().add(cameraZRotation);
root.getChildren().add(camera);
geomScene.setCamera(camera);
setupMeshViewControls();
}
private void setupMeshViewControls() {
meshView.setOnMousePressed(me -> {
if (me.getButton() == MouseButton.PRIMARY) {
dragX = me.getScreenX();
dragY = me.getScreenY();
}
if (me.getButton() == MouseButton.SECONDARY) {
dragX = me.getScreenX();
dragY = me.getScreenY();
}
});
meshView.setOnScroll(se -> {
if (se.getDeltaY() < 0) {
translateZ += translateZ * 0.05;
} else {
translateZ -= translateZ * 0.05;
}
camera.setTranslateZ(translateZ);
highlightController.changeScaling(translateZ);
});
meshView.setOnMouseDragged(me -> {
if (me.getButton() == MouseButton.PRIMARY) {
double deltaX = me.getScreenX() - dragX;
double deltaY = me.getScreenY() - dragY;
dragX = me.getScreenX();
dragY = me.getScreenY();
cameraXRot += (deltaX / 3d) % 360;
cameraYRot += (deltaY / 3d) % 360;
cameraZRotation.setAngle(cameraXRot);
cameraXRotation.setAngle(cameraYRot);
alignNorthArrow();
}
if (me.getButton() == MouseButton.SECONDARY) {
double translationSpeed = Math.abs(camera.getTranslateZ()) / 1000;
double deltaX = me.getScreenX() - dragX;
double deltaY = me.getScreenY() - dragY;
dragX = me.getScreenX();
dragY = me.getScreenY();
camera.setTranslateX(camera.getTranslateX() - deltaX * translationSpeed);
camera.setTranslateY(camera.getTranslateY() - deltaY * translationSpeed);
}
});
}
private void buildCamera() {
camera = new PerspectiveCamera(true);
camera.setNearClip(0.1);
camera.setFarClip(10000d);
camera.setTranslateZ(translateZ);
cameraZRotation.setAngle(cameraXRot);
cameraXRotation.setAngle(cameraYRot);
} }
public void alignNorthArrow() { public void alignNorthArrow() {
double absRotZ = cameraZRotation.getAngle() - 360 * Math.floor(cameraZRotation.getAngle() / 360); double azimuth = glViewport.camera().azimuthDeg();
double absRotX = cameraXRotation.getAngle() - 360 * Math.floor(cameraXRotation.getAngle() / 360); double elevation = glViewport.camera().elevationDeg();
double absRotZ = azimuth - 360 * Math.floor(azimuth / 360);
double absRotX = elevation - 360 * Math.floor(elevation / 360);
double northRot; double northRot;
if (80 <= absRotX && absRotX <= 260) { if (80 <= absRotX && absRotX <= 260) {
...@@ -978,16 +891,8 @@ public class MainWindow extends Application { ...@@ -978,16 +891,8 @@ public class MainWindow extends Application {
} }
public void resetCamera() { public void resetCamera() {
cameraXRot = CAMERA_INITIAL_X_ANGLE; glViewport.resetCamera();
cameraYRot = CAMERA_INITIAL_Y_ANGLE;
cameraZRotation.setAngle(cameraXRot);
cameraXRotation.setAngle(cameraYRot);
alignNorthArrow(); alignNorthArrow();
camera.setTranslateX(0);
camera.setTranslateY(0);
if (controller.getOriginBB() != null) {
zoomOutForBoundingBox(controller.getOriginBB());
}
} }
public void addFileNameToTitle(String fileName) { public void addFileNameToTitle(String fileName) {
...@@ -1055,8 +960,14 @@ public class MainWindow extends Application { ...@@ -1055,8 +960,14 @@ public class MainWindow extends Application {
return mainToolBar.getGridButton(); return mainToolBar.getGridButton();
} }
public Group getMeshGroup() { public GLViewport getGlViewport() {
return meshGroup; return glViewport;
}
/** Clears whatever geometry is currently displayed in the 3D view. */
public void clearMeshView() {
glViewport.setScene(null);
glViewport.setIndexSet(new int[0]);
} }
public ToggleButton getCullingButton() { public ToggleButton getCullingButton() {
...@@ -1137,20 +1048,16 @@ public class MainWindow extends Application { ...@@ -1137,20 +1048,16 @@ public class MainWindow extends Application {
} }
public void takeViewScreenshot() throws IOException { public void takeViewScreenshot() throws IOException {
WritableImage snapshot = geomScene.snapshot(null, null); WritableImage snapshot = glViewport.getNode().snapshot(null, null);
File outputFile = new File("img.png"); File outputFile = new File("img.png");
BufferedImage bImage = SwingFXUtils.fromFXImage(snapshot, null); BufferedImage bImage = SwingFXUtils.fromFXImage(snapshot, null);
ImageIO.write(bImage, "png", outputFile); ImageIO.write(bImage, "png", outputFile);
} }
public void zoomOutForBoundingBox(BoundingBox b) { public void zoomOutForBoundingBox(BoundingBox b) {
double longestSide = b.getDiagonalLength() * 0.4; glViewport.camera().zoomOutForBoundingBox(b.getDiagonalLength());
double d = longestSide / Math.tan(Math.toRadians(30) / 2); glViewport.getNode().repaint();
translateZ = -d; highlightController.changeScaling(glViewport.camera().distance());
camera.setTranslateZ(translateZ);
camera.setTranslateX(0);
camera.setTranslateY(0);
highlightController.changeScaling(-translateZ);
controller.setOriginBB(b); controller.setOriginBB(b);
} }
......
...@@ -4,7 +4,6 @@ import de.hft.stuttgart.citydoctor2.check.CheckError; ...@@ -4,7 +4,6 @@ import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.Checkable; import de.hft.stuttgart.citydoctor2.check.Checkable;
import de.hft.stuttgart.citydoctor2.utils.visitors.CityObjectCollector; import de.hft.stuttgart.citydoctor2.utils.visitors.CityObjectCollector;
import de.hft.stuttgart.citydoctor2.datastructure.*; import de.hft.stuttgart.citydoctor2.datastructure.*;
import de.hft.stuttgart.citydoctor2.gui.filter.ViewFilter;
import de.hft.stuttgart.citydoctor2.gui.tree.*; import de.hft.stuttgart.citydoctor2.gui.tree.*;
import de.hft.stuttgart.citydoctor2.gui.tree.node.EdgeNode; import de.hft.stuttgart.citydoctor2.gui.tree.node.EdgeNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.ErrorNode; import de.hft.stuttgart.citydoctor2.gui.tree.node.ErrorNode;
...@@ -12,12 +11,15 @@ import de.hft.stuttgart.citydoctor2.gui.tree.node.GenericAttributeNode; ...@@ -12,12 +11,15 @@ import de.hft.stuttgart.citydoctor2.gui.tree.node.GenericAttributeNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.LinearRingNode; import de.hft.stuttgart.citydoctor2.gui.tree.node.LinearRingNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.PolygonNode; import de.hft.stuttgart.citydoctor2.gui.tree.node.PolygonNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.VertexNode; import de.hft.stuttgart.citydoctor2.gui.tree.node.VertexNode;
import de.hft.stuttgart.citydoctor2.gui.gl.GLViewport;
import de.hft.stuttgart.citydoctor2.gui.gl.IndexSetBuilder;
import de.hft.stuttgart.citydoctor2.gui.gl.SceneBuilder;
import de.hft.stuttgart.citydoctor2.gui.gl.SceneData;
import de.hft.stuttgart.citydoctor2.gui.gl.TriangleMeta;
import de.hft.stuttgart.citydoctor2.math.Triangle3d; import de.hft.stuttgart.citydoctor2.math.Triangle3d;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -28,11 +30,15 @@ public class Renderer { ...@@ -28,11 +30,15 @@ public class Renderer {
private static final Logger logger = LogManager.getLogger(Renderer.class); private static final Logger logger = LogManager.getLogger(Renderer.class);
private TriangulatedGeometry currentTriGeom; private SceneData currentScene;
private Geometry currentGeometry; private Geometry currentGeometry;
private CullFace currentCulling = CullFace.NONE; private boolean culling = false;
private DrawMode currentDrawMode = DrawMode.FILL; private boolean wireframe = false;
// LOD visibility, indexed by Lod.ordinal() (LOD0..LOD4); all enabled by default
private final boolean[] lodEnabled = {true, true, true, true, true};
private boolean roofsHidden = false;
private MainWindow mainWindow; private MainWindow mainWindow;
private HighlightController highlightController; private HighlightController highlightController;
...@@ -40,8 +46,6 @@ public class Renderer { ...@@ -40,8 +46,6 @@ public class Renderer {
private LoadingInfoDialog loadingDialog; private LoadingInfoDialog loadingDialog;
private List<ViewFilter> lodFilters = new ArrayList<>();
private ViewFilter roofFilter;
private Runnable refresher; private Runnable refresher;
private Runnable errorUpdater; private Runnable errorUpdater;
...@@ -50,138 +54,74 @@ public class Renderer { ...@@ -50,138 +54,74 @@ public class Renderer {
this.highlightController = highlightController; this.highlightController = highlightController;
loadingDialog = new LoadingInfoDialog(mainWindow.getMainStage()); loadingDialog = new LoadingInfoDialog(mainWindow.getMainStage());
errVisitor = new ListErrorVisitor(highlightController); errVisitor = new ListErrorVisitor(highlightController);
setupLodFilters();
} }
private void setupLodFilters() { private boolean triangleVisible(TriangleMeta m) {
lodFilters.add(new ViewFilter() { int lod = m.lod();
boolean lodOk = lod < 0 || lod >= lodEnabled.length || lodEnabled[lod];
@Override if (!lodOk) {
public boolean useGeometry(CityObject co, Geometry geom) { return false;
return geom.getLod() == Lod.LOD1;
} }
return !roofsHidden || !m.roof();
});
lodFilters.add(new ViewFilter() {
@Override
public boolean useGeometry(CityObject co, Geometry geom) {
return geom.getLod() == Lod.LOD2;
}
});
lodFilters.add(new ViewFilter() {
@Override
public boolean useGeometry(CityObject co, Geometry geom) {
return geom.getLod() == Lod.LOD3;
} }
}); private void rebuildIndexSet() {
lodFilters.add(new ViewFilter() { if (currentScene == null) {
return;
@Override
protected boolean useGeometry(CityObject co, Geometry geom) {
return geom.getLod() == Lod.LOD0;
}
});
lodFilters.add(new ViewFilter() {
@Override
public boolean useGeometry(CityObject co, Geometry geom) {
return geom.getLod() == Lod.LOD4;
}
});
roofFilter = new ViewFilter() {
@Override
public boolean allowedToUse(CityObject co, Geometry geom) {
if (!this.isEnabled()) {
return true;
}
return this.useGeometry(co, geom);
}
@Override
public boolean useGeometry(CityObject co, Geometry geom) {
if (co instanceof BoundarySurface bs) {
return bs.getType() != BoundarySurfaceType.ROOF;
}
return true;
} }
mainWindow.getGlViewport().setIndexSet(
}; IndexSetBuilder.build(currentScene.triangleMetas(), this::triangleVisible));
roofFilter.setEnable(false);
} }
public void enableLod1() { public void enableLod1() {
lodFilters.get(0).enable(); setLodEnabled(Lod.LOD1.ordinal(), true);
if (refresher != null) {
refresher.run();
}
} }
public void disableLod1() { public void disableLod1() {
lodFilters.get(0).disable(); setLodEnabled(Lod.LOD1.ordinal(), false);
if (refresher != null) {
refresher.run();
}
} }
public void enableLod2() { public void enableLod2() {
lodFilters.get(1).enable(); setLodEnabled(Lod.LOD2.ordinal(), true);
if (refresher != null) {
refresher.run();
}
} }
public void disableLod2() { public void disableLod2() {
lodFilters.get(1).disable(); setLodEnabled(Lod.LOD2.ordinal(), false);
if (refresher != null) {
refresher.run();
}
} }
public void enableLod3() { public void enableLod3() {
lodFilters.get(2).enable(); setLodEnabled(Lod.LOD3.ordinal(), true);
if (refresher != null) {
refresher.run();
}
} }
public void disableLod3() { public void disableLod3() {
lodFilters.get(2).disable(); setLodEnabled(Lod.LOD3.ordinal(), false);
if (refresher != null) {
refresher.run();
}
} }
public void enableLod4() { public void enableLod4() {
lodFilters.get(3).enable(); setLodEnabled(Lod.LOD4.ordinal(), true);
if (refresher != null) {
refresher.run();
}
} }
public void disableLod4() { public void disableLod4() {
lodFilters.get(3).disable(); setLodEnabled(Lod.LOD4.ordinal(), false);
if (refresher != null) { }
refresher.run();
private void setLodEnabled(int lodOrdinal, boolean enabled) {
// legacy LOD0 followed LOD3 button; keep LOD0 tied to LOD3 toggle for parity
lodEnabled[lodOrdinal] = enabled;
if (lodOrdinal == Lod.LOD3.ordinal()) {
lodEnabled[Lod.LOD0.ordinal()] = enabled;
} }
Platform.runLater(this::rebuildIndexSet);
} }
public void hideRoofs() { public void hideRoofs() {
roofFilter.setEnable(true); roofsHidden = true;
if (refresher != null) { Platform.runLater(this::rebuildIndexSet);
refresher.run();
}
} }
public void showRoofs() { public void showRoofs() {
roofFilter.setEnable(false); roofsHidden = false;
if (refresher != null) { Platform.runLater(this::rebuildIndexSet);
refresher.run();
}
} }
public void setupRefresher(CityObject co) { public void setupRefresher(CityObject co) {
...@@ -207,20 +147,9 @@ public class Renderer { ...@@ -207,20 +147,9 @@ public class Renderer {
private void addPolygons(CityObject co, Set<ConcretePolygon> polygons) { private void addPolygons(CityObject co, Set<ConcretePolygon> polygons) {
for (Geometry geom : co.getGeometries()) { for (Geometry geom : co.getGeometries()) {
boolean used = false;
for (ViewFilter filter : lodFilters) {
if (filter.allowedToUse(co, geom)) {
used = true;
break;
}
}
if (used) {
if (roofFilter.allowedToUse(co, geom)) {
addConcretePolygons(polygons, geom); addConcretePolygons(polygons, geom);
} }
} }
}
}
private void displayErrors(Checkable c) { private void displayErrors(Checkable c) {
if (!c.isValidated()) { if (!c.isValidated()) {
...@@ -244,15 +173,14 @@ public class Renderer { ...@@ -244,15 +173,14 @@ public class Renderer {
public void render(Geometry geom) { public void render(Geometry geom) {
refresher = () -> { refresher = () -> {
Platform.runLater(this::clearGeometryTrees); Platform.runLater(this::clearGeometryTrees);
currentTriGeom = TriangulatedGeometry.of(geom); SceneData scene = SceneBuilder.fromPolygons(geom.getPolygons(), Color.WHITE);
if (geom.getEdges() == null && currentGeometry != null) { if (geom.getEdges() == null && currentGeometry != null) {
// if there are no edges available low memory mode is enabled // if there are no edges available low memory mode is enabled
// clear the old geometry of all meta information // clear the old geometry of all meta information
currentGeometry.clearMetaData(); currentGeometry.clearMetaData();
} }
errVisitor.setGeometry(currentTriGeom);
Platform.runLater(() -> { Platform.runLater(() -> {
setupRenderState(); applyScene(scene);
if (geom.getEdges() == null) { if (geom.getEdges() == null) {
// create edges and vertices so they can be listed in the gui // create edges and vertices so they can be listed in the gui
geom.prepareForChecking(); geom.prepareForChecking();
...@@ -349,9 +277,8 @@ public class Renderer { ...@@ -349,9 +277,8 @@ public class Renderer {
private void render(Collection<? extends Polygon> polygons) { private void render(Collection<? extends Polygon> polygons) {
Platform.runLater(this::clearGeometryTrees); Platform.runLater(this::clearGeometryTrees);
currentTriGeom = TriangulatedGeometry.of(polygons); SceneData scene = SceneBuilder.fromPolygons(polygons, Color.WHITE);
errVisitor.setGeometry(currentTriGeom); Platform.runLater(() -> applyScene(scene));
setupRenderState();
} }
private void clearGeometryTrees() { private void clearGeometryTrees() {
...@@ -375,10 +302,9 @@ public class Renderer { ...@@ -375,10 +302,9 @@ public class Renderer {
clearAttributes(); clearAttributes();
}); });
Thread t = new Thread(() -> { Thread t = new Thread(() -> {
currentTriGeom = TriangulatedGeometry.of(model, lodFilters); SceneData scene = SceneBuilder.fromModel(model);
errVisitor.setGeometry(currentTriGeom);
Platform.runLater(() -> { Platform.runLater(() -> {
setupRenderState(); applyScene(scene);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(model)); mainWindow.zoomOutForBoundingBox(BoundingBox.of(model));
loadingDialog.hide(); loadingDialog.hide();
}); });
...@@ -430,14 +356,10 @@ public class Renderer { ...@@ -430,14 +356,10 @@ public class Renderer {
CityObjectCollector collector = new CityObjectCollector(); CityObjectCollector collector = new CityObjectCollector();
cos.forEach(cityObject -> cityObject.accept(collector)); cos.forEach(cityObject -> cityObject.accept(collector));
collector.getCityObjects().forEach(cityObject -> addPolygons(cityObject, polygons)); collector.getCityObjects().forEach(cityObject -> addPolygons(cityObject, polygons));
if (baseColor != null) { Color base = baseColor != null ? baseColor : Color.WHITE;
currentTriGeom = TriangulatedGeometry.of(polygons, baseColor); SceneData scene = SceneBuilder.fromPolygons(polygons, base);
} else {
currentTriGeom = TriangulatedGeometry.of(polygons);
}
errVisitor.setGeometry(currentTriGeom);
Platform.runLater(() -> { Platform.runLater(() -> {
setupRenderState(); applyScene(scene);
mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons)); mainWindow.zoomOutForBoundingBox(BoundingBox.of(polygons));
loadingDialog.hide(); loadingDialog.hide();
}); });
...@@ -455,49 +377,44 @@ public class Renderer { ...@@ -455,49 +377,44 @@ public class Renderer {
private void addConcretePolygons(Set<ConcretePolygon> polygons, Geometry geom) { private void addConcretePolygons(Set<ConcretePolygon> polygons, Geometry geom) {
for (Polygon p : geom.getPolygons()) { for (Polygon p : geom.getPolygons()) {
if (p.getOriginal().getPartOfSurface() != null &&
!roofFilter.allowedToUse(p.getOriginal().getPartOfSurface(), p.getParent())) continue;
polygons.add(p.getOriginal()); polygons.add(p.getOriginal());
} }
} }
private void setupRenderState() { /**
currentTriGeom.setCullFace(currentCulling); * Installs the freshly built scene into the viewport (FX thread), wires the highlight center
currentTriGeom.setDrawMode(currentDrawMode); * supplier, applies the current wireframe/cull state and rebuilds the visible index set.
Platform.runLater(() -> { */
mainWindow.getMeshGroup().getChildren().clear(); private void applyScene(SceneData scene) {
mainWindow.getMeshGroup().getChildren().addAll(currentTriGeom.getMeshes()); currentScene = scene;
}); GLViewport viewport = mainWindow.getGlViewport();
viewport.setScene(scene);
highlightController.setCenterSupplier(
() -> currentScene == null ? new double[3] : currentScene.center());
viewport.setWireframe(wireframe);
viewport.setCulling(culling);
rebuildIndexSet();
mainWindow.getGridButton().setDisable(false); mainWindow.getGridButton().setDisable(false);
mainWindow.getCullingButton().setDisable(false); mainWindow.getCullingButton().setDisable(false);
} }
public void showWireFrame(boolean show) { public void showWireFrame(boolean show) {
if (currentTriGeom != null) { wireframe = show;
if (show) { mainWindow.getGlViewport().setWireframe(show);
currentDrawMode = DrawMode.LINE;
} else {
currentDrawMode = DrawMode.FILL;
}
currentTriGeom.setDrawMode(currentDrawMode);
}
} }
public void enableCulling(boolean enable) { public void enableCulling(boolean enable) {
if (currentTriGeom != null) { culling = enable;
if (enable) { mainWindow.getGlViewport().setCulling(enable);
currentCulling = CullFace.BACK;
} else {
currentCulling = CullFace.NONE;
}
currentTriGeom.setCullFace(currentCulling);
}
} }
public void clearCurrentRender() { public void clearCurrentRender() {
// don't render anything // don't render anything
currentScene = null;
Platform.runLater(() -> { Platform.runLater(() -> {
mainWindow.getMeshGroup().getChildren().clear(); GLViewport viewport = mainWindow.getGlViewport();
viewport.setScene(null);
viewport.setIndexSet(new int[0]);
clearGeometryTrees(); clearGeometryTrees();
clearAttributes(); clearAttributes();
}); });
...@@ -508,35 +425,35 @@ public class Renderer { ...@@ -508,35 +425,35 @@ public class Renderer {
} }
public void highlight(Polygon p) { public void highlight(Polygon p) {
highlightController.highlight(p, currentTriGeom); highlightController.highlight(p);
} }
public void highlight(LinearRing lr) { public void highlight(LinearRing lr) {
highlightController.highlight(lr, currentTriGeom); highlightController.highlight(lr);
} }
public void highlight(Edge e) { public void highlight(Edge e) {
highlightController.highlight(e, currentTriGeom); highlightController.highlight(e);
} }
public void highlight(Vertex v) { public void highlight(Vertex v) {
highlightController.highlight(v, currentTriGeom); highlightController.highlight(v);
} }
public void highlight(List<LinearRing> highlightedRings) { public void highlight(List<LinearRing> highlightedRings) {
highlightController.highlight(highlightedRings, currentTriGeom); highlightController.highlight(highlightedRings);
} }
public void highlightEdges(List<Edge> edges) { public void highlightEdges(List<Edge> edges) {
highlightController.highlightEdges(edges, currentTriGeom); highlightController.highlightEdges(edges);
} }
public void highlightPolygons(List<List<Polygon>> components) { public void highlightPolygons(List<List<Polygon>> components) {
highlightController.highlightPolygons(components, currentTriGeom); highlightController.highlightPolygons(components);
} }
public void addHighlight(Vertex vertex, Color c) { public void addHighlight(Vertex vertex, Color c) {
highlightController.addHighlight(vertex, currentTriGeom, c); highlightController.addHighlight(vertex, c);
} }
public void highlight(CheckError err) { public void highlight(CheckError err) {
...@@ -560,11 +477,11 @@ public class Renderer { ...@@ -560,11 +477,11 @@ public class Renderer {
} }
public void addHighlight(Polygon p) { public void addHighlight(Polygon p) {
highlightController.addHighlight(p, currentTriGeom); highlightController.addHighlight(p);
} }
public void addHighlight(Triangle3d t) { public void addHighlight(Triangle3d t) {
highlightController.highlight(t, currentTriGeom); highlightController.highlight(t);
} }
public void reset() { public void reset() {
......
...@@ -46,7 +46,7 @@ public class ValidationView extends View { ...@@ -46,7 +46,7 @@ public class ValidationView extends View {
public void onHide() { public void onHide() {
Platform.runLater(() -> { Platform.runLater(() -> {
mainWindow.unselectEverything(); mainWindow.unselectEverything();
mainWindow.getMeshGroup().getChildren().clear(); mainWindow.clearMeshView();
mainWindow.clearHighlights(); mainWindow.clearHighlights();
mainWindow.getErrorTree().getRoot().getChildren().clear(); mainWindow.getErrorTree().getRoot().getChildren().clear();
mainWindow.getPolygonsView().getRoot().getChildren().clear(); mainWindow.getPolygonsView().getRoot().getChildren().clear();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment