Commit 297334ab authored by Matthias Betz's avatar Matthias Betz
Browse files

Add design spec for OpenGL 3D view



Replaces the JavaFX SubScene/MeshView rendering with an OpenGL viewport
(openglfx-jogl, GL 3.3 core), single global VBO, GPU color-picking, and
baked fake shading. Windows/Linux targets; JavaFX 3D path removed.

Co-Authored-By: default avatarClaude Opus 4.8 <noreply@anthropic.com>
parents 5c2847ef bd40b396
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractRoom;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllRoomsNode extends Renderable{
private final List<? extends AbstractRoom> rooms;
public AllRoomsNode(List<? extends AbstractRoom> rooms) {
this.rooms = rooms;
}
@Override
public String getText() {
return "Building Rooms";
}
@Override
public void visit(Renderer renderer) {
renderer.clearCurrentRender();
}
@Override
public void refreshTextColor() {
boolean wasChecked = false;
for (AbstractRoom ar : rooms) {
if (ar.isValidated()) {
wasChecked = true;
if (ar.containsAnyError()) {
setStatus(CheckStatus.ERROR);
return;
}
}
}
if (wasChecked) {
setStatus(CheckStatus.OK);
} else {
setStatus(CheckStatus.NOT_CHECKED);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.Storey;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllStoreysNode extends Renderable{
private final List<Storey> storeys;
public AllStoreysNode(List<Storey> storeys) {
this.storeys = storeys;
}
@Override
public String getText() {
return "Building Storeys";
}
@Override
public void visit(Renderer renderer) {
renderer.clearCurrentRender();
}
@Override
public void refreshTextColor() {
boolean wasChecked = false;
for (Storey storey : storeys) {
if (storey.isValidated()) {
wasChecked = true;
if (storey.containsAnyError()) {
setStatus(CheckStatus.ERROR);
return;
}
}
}
if (wasChecked) {
setStatus(CheckStatus.OK);
} else {
setStatus(CheckStatus.NOT_CHECKED);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class AllTerrainNode extends Renderable {
private final List<CityObject> land;
public AllTerrainNode(List<CityObject> land) {
this.land = land;
}
@Override
public void refreshTextColor() {
// no use
}
@Override
public String getText() {
return "Terrain";
}
@Override
public void visit(Renderer renderer) {
renderer.renderTerrain(land);
}
}
/*-
* Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.gui.tree;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.TinObject;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class AllTinNode extends Renderable {
public AllTinNode(List<TinObject> components) {}
@Override
public void refreshTextColor() {}
@Override
public String getText() {
return "Components";
}
@Override
public void visit(Renderer renderer) {}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class AllTransportationNode extends Renderable {
private final List<TransportationObject> transportation;
public AllTransportationNode(List<TransportationObject> transportation) {
this.transportation = transportation;
}
@Override
public void refreshTextColor() {
// no use
}
@Override
public String getText() {
return "Transportation";
}
@Override
public void visit(Renderer renderer) {
renderer.renderTransportation(transportation);
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.TunnelPart;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllTunnelPartsNode extends Renderable{
private final List<TunnelPart> tunnelParts;
public AllTunnelPartsNode(List<TunnelPart> tunnelParts) {
this.tunnelParts = tunnelParts;
}
@Override
public String getText() {
return "Tunnel Parts";
}
@Override
public void visit(Renderer renderer) {
renderer.clearCurrentRender();
}
@Override
public void refreshTextColor() {
boolean wasChecked = false;
for (TunnelPart tp : tunnelParts) {
if (tp.isValidated()) {
wasChecked = true;
if (tp.containsAnyError()) {
setStatus(CheckStatus.ERROR);
return;
}
}
}
if (wasChecked) {
setStatus(CheckStatus.OK);
} else {
setStatus(CheckStatus.NOT_CHECKED);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.Tunnel;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
import java.util.List;
public class AllTunnelsNode extends Renderable{
private final List<Tunnel> tunnels;
public AllTunnelsNode(List<Tunnel> tunnels) {
this.tunnels = tunnels;
}
@Override
public void refreshTextColor() {
// no color changes
}
@Override
public String getText() {
return "Tunnels";
}
@Override
public void visit(Renderer renderer) {
renderer.renderTunnels(tunnels);
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class AllVegetationNode extends Renderable {
private final List<Vegetation> vegetation;
public AllVegetationNode(List<Vegetation> vegetation) {
this.vegetation = vegetation;
}
@Override
public void refreshTextColor() {
// no use
}
@Override
public String getText() {
return "Vegetation";
}
@Override
public void visit(Renderer renderer) {
renderer.renderVegetation(vegetation);
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.WaterObject;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class AllWaterNode extends Renderable {
private final List<WaterObject> water;
public AllWaterNode(List<WaterObject> water) {
this.water = water;
}
@Override
public void refreshTextColor() {
// no use
}
@Override
public String getText() {
return "Water";
}
@Override
public void visit(Renderer renderer) {
renderer.renderWater(water);
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class BoundarySurfaceNode extends Renderable {
private final BoundarySurface bs;
public BoundarySurfaceNode(BoundarySurface bs) {
this.bs = bs;
}
@Override
public String getText() {
return bs.getGmlId().getGmlString() + " [" + bs.getType() + "]";
}
@Override
public void visit(Renderer renderer) {
renderer.render(bs);
}
@Override
public void refreshTextColor() {
if (!bs.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (bs.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
/*-
* Copyright 2023 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeConstructiveElement;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class BridgeConstructiveElementNode extends Renderable {
private final BridgeConstructiveElement bce;
public BridgeConstructiveElementNode(BridgeConstructiveElement bce) {
this.bce = bce;
}
@Override
public String getText() {
return bce.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(bce);
}
@Override
public void refreshTextColor() {
if (!bce.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (bce.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
/*-
* Copyright 2022 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class BridgeNode extends Renderable {
private final BridgeObject bridge;
public BridgeNode(BridgeObject bridge) {
this.bridge = bridge;
}
@Override
public String getText() {
return bridge.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(bridge);
}
@Override
public void refreshTextColor() {
if (!bridge.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (bridge.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class BuildingNode extends Renderable {
private final Building building;
public BuildingNode(Building building) {
this.building = building;
}
@Override
public String getText() {
return building.getGmlId().getGmlString();
}
public Building getBuilding() {
return building;
}
@Override
public void visit(Renderer renderer) {
renderer.render(building);
}
@Override
public void refreshTextColor() {
if (!building.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (building.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class BuildingPartNode extends Renderable {
private final BuildingPart bp;
public BuildingPartNode(BuildingPart bp) {
this.bp = bp;
}
@Override
public String getText() {
return bp.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(bp);
}
@Override
public void refreshTextColor() {
if (!bp.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (bp.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingUnit;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class BuildingUnitNode extends Renderable{
private final BuildingUnit buildingUnit;
public BuildingUnitNode(BuildingUnit buildingUnit) {
this.buildingUnit = buildingUnit;
}
@Override
public String getText() {
return buildingUnit.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(buildingUnit);
}
@Override
public void refreshTextColor() {
if (!buildingUnit.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (buildingUnit.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.CityFurniture;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class CityFurnitureNode extends Renderable{
private final CityFurniture cityFurniture;
public CityFurnitureNode(CityFurniture cityFurniture) {
this.cityFurniture = cityFurniture;
}
@Override
public String getText() {
return cityFurniture.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(cityFurniture);
}
@Override
public void refreshTextColor() {
if (!cityFurniture.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (cityFurniture.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
......@@ -2,13 +2,14 @@ package de.hft.stuttgart.citydoctor2.gui.tree;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.AbstractErrorVisitor;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.ErrorVisitor;
import de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError;
import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError;
import de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError;
import de.hft.stuttgart.citydoctor2.check.error.NestedRingError;
......@@ -35,8 +36,7 @@ import de.hft.stuttgart.citydoctor2.check.error.RingTooFewPointsError;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.SurfaceFragmentedError;
import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
import de.hft.stuttgart.citydoctor2.datastructure.ConcretePolygon;
......@@ -46,13 +46,18 @@ import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.tree.node.EdgeNode;
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.TextNode;
import de.hft.stuttgart.citydoctor2.gui.tree.node.VertexNode;
import de.hft.stuttgart.citydoctor2.math.Triangle3d;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection;
import de.hft.stuttgart.citydoctor2.utils.PolygonIntersection.IntersectionType;
import javafx.scene.control.TreeItem;
public class ErrorItemVisitor implements ErrorVisitor {
public class ErrorItemVisitor extends AbstractErrorVisitor {
private static String nameOfAttribute = Localization.getText("ErrorItemVisitor.nameOfAttribute") + ": ";
private static String childId = Localization.getText("ErrorItemVisitor.childId") + ": ";
......@@ -391,7 +396,7 @@ public class ErrorItemVisitor implements ErrorVisitor {
}
@Override
public void visit(SurfaceUnfragmentedError err) {
public void visit(SurfaceFragmentedError err) {
TextNode textNode = new TextNode(
Localization.getText("ErrorItemVisitor.deviation") + ": " + err.getAngleDeviation());
TreeItem<Renderable> textItem = new TreeItem<>(textNode);
......
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractFurniture;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class FurnitureNode extends Renderable{
private final AbstractFurniture furniture;
public FurnitureNode(AbstractFurniture furniture) {
this.furniture = furniture;
}
@Override
public String getText() {
return furniture.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(furniture);
}
@Override
public void refreshTextColor() {
if (!furniture.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (furniture.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.GenericCityObject;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class GenericCityObjectsNode extends Renderable{
private final GenericCityObject gcobject;
public GenericCityObjectsNode(GenericCityObject gcobject) {
this.gcobject = gcobject;
}
@Override
public String getText() {
return gcobject.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(gcobject);
}
@Override
public void refreshTextColor() {
if (!gcobject.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (gcobject.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
package de.hft.stuttgart.citydoctor2.gui.tree;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.gui.CheckStatus;
import de.hft.stuttgart.citydoctor2.gui.Renderer;
public class InstallationNode extends Renderable {
private final Installation bi;
public InstallationNode(Installation bi) {
this.bi = bi;
}
@Override
public String getText() {
return bi.getGmlId().getGmlString();
}
@Override
public void visit(Renderer renderer) {
renderer.render(bi);
}
@Override
public void refreshTextColor() {
if (!bi.isValidated()) {
setStatus(CheckStatus.NOT_CHECKED);
} else if (bi.containsAnyError()) {
setStatus(CheckStatus.ERROR);
} else {
setStatus(CheckStatus.OK);
}
}
}
\ No newline at end of file
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