Commit 19a9b8c6 authored by Matthias Betz's avatar Matthias Betz
Browse files

only using opengl 3.0

added more geometry parsing
added parallel parsing
parent 0f66af82
Showing with 518 additions and 318 deletions
+518 -318
......@@ -7,8 +7,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<lwjgl.version>3.2.3</lwjgl.version>
<joml.version>1.10.1</joml.version>
</properties>
......@@ -65,17 +65,24 @@
</dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.citygml4j/citygml4j -->
<!-- https://mvnrepository.com/artifact/org.citygml4j/citygml4j-core -->
<dependency>
<groupId>org.citygml4j</groupId>
<artifactId>citygml4j</artifactId>
<version>3.0.0-rc.2</version>
<artifactId>citygml4j-core</artifactId>
<version>3.0.0-rc.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.citygml4j/citygml4j-xml -->
<dependency>
<groupId>org.citygml4j</groupId>
<artifactId>citygml4j-xml</artifactId>
<version>3.0.0-rc.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.locationtech.proj4j/proj4j -->
<dependency>
<groupId>org.locationtech.proj4j</groupId>
<artifactId>proj4j</artifactId>
<version>1.1.3</version>
<version>1.1.5</version>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
......
......@@ -25,17 +25,24 @@ import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import org.citygml4j.CityGMLContext;
import org.citygml4j.CityGMLContextException;
import org.citygml4j.model.core.AbstractCityObject;
import org.citygml4j.model.core.AbstractFeature;
import org.citygml4j.xml.reader.ChunkingOptions;
import org.citygml4j.core.model.core.AbstractFeature;
import org.citygml4j.core.util.CityGMLConstants;
import org.citygml4j.xml.CityGMLContext;
import org.citygml4j.xml.CityGMLContextException;
import org.citygml4j.xml.reader.ChunkOptions;
import org.citygml4j.xml.reader.CityGMLChunk;
import org.citygml4j.xml.reader.CityGMLInputFactory;
import org.citygml4j.xml.reader.CityGMLReadException;
import org.citygml4j.xml.reader.CityGMLReader;
......@@ -58,6 +65,7 @@ import org.xml.sax.SAXException;
import com.jogamp.opengl.GLException;
import de.hft.stuttgart.citygml.viewer.datastructure.BoundingBox;
import de.hft.stuttgart.citygml.viewer.datastructure.Polygon;
import de.hft.stuttgart.citygml.viewer.math.Vector3d;
import de.hft.stuttgart.citygml.viewer.parser.CityGMLParser;
import de.hft.stuttgart.citygml.viewer.parser.FeatureMapper;
......@@ -86,6 +94,15 @@ public class CityGMLViewer {
private static ProgressBar bar;
private static final String CITY_OBJECT_MEMBER = "cityObjectMember";
private static List<QName> chunkProperties = new ArrayList<>();
static {
chunkProperties.add(new QName(CityGMLConstants.CITYGML_1_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
chunkProperties.add(new QName(CityGMLConstants.CITYGML_2_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
chunkProperties.add(new QName(CityGMLConstants.CITYGML_3_0_CORE_NAMESPACE, CITY_OBJECT_MEMBER));
}
public static void main(String[] args) {
File f = null;
if (args != null && args.length == 1) {
......@@ -173,9 +190,8 @@ public class CityGMLViewer {
GLFW.glfwDefaultWindowHints(); // Loads GLFW's default window settings
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); // Sets window to be visible
GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_TRUE); // Sets whether the window is resizable
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0);
GLFW.glfwWindowHint(GLFW.GLFW_SAMPLES, 2);
windowId = GLFW.glfwCreateWindow(width, height, title, 0, 0);
......@@ -271,8 +287,8 @@ public class CityGMLViewer {
// NO_CURRENT_CONTEXT error
org.lwjgl.opengl.GLCapabilities caps = GL.createCapabilities(); // Will let lwjgl know we want to use this
// context as the context to draw with
if (!caps.OpenGL33) {
log.warning("OpenGL 33 is not supported");
if (!caps.OpenGL30) {
log.warning("OpenGL 3.0 is not supported");
}
GLFW.glfwSwapInterval(1); // How many draws to swap the buffer
......@@ -284,7 +300,7 @@ public class CityGMLViewer {
GLFW.glfwShowWindow(windowId); // Shows the window
if (log.isLoggable(Level.INFO)) {
log.info("OpenGL error code after displaying the window: " + GL11.glGetError());
log.fine("OpenGL error code after displaying the window: " + GL11.glGetError());
}
FloatBuffer clearColor = null;
......@@ -293,24 +309,19 @@ public class CityGMLViewer {
try {
Shader program = new Shader("vertex.vert", "fragment.frag");
program.use();
if (log.isLoggable(Level.INFO)) {
log.info("OpenGL error code after shader loading: " + GL11.glGetError());
}
log.fine(() -> "OpenGL error code after shader loading: " + GL11.glGetError());
camera = new Camera(program);
camera.setOrtho(true);
camera.reshape(width, height, cameraViewDistance);
bar = new ProgressBar(windowId, width, height);
bar.drawProgress(0);
if (log.isLoggable(Level.INFO)) {
log.info("OpenGL error code after drawing initial progress bar: " + GL11.glGetError());
}
log.fine(() -> "OpenGL error code after drawing initial progress bar: " + GL11.glGetError());
loadGmlFile(f);
log.fine(() -> "OpenGL error code after loading GML file: " + GL11.glGetError());
bar.free();
bar = null;
if (log.isLoggable(Level.INFO)) {
log.info("OpenGL error code after loading GML file: " + GL11.glGetError());
}
camera.setOrtho(false);
camera.reshape(width, height, cameraViewDistance);
......@@ -319,9 +330,7 @@ public class CityGMLViewer {
clearDepth = MemoryUtil.memAllocFloat(1);
clearDepth.put(0, 1f);
if (log.isLoggable(Level.INFO)) {
log.info("OpenGL error code before loop: " + GL11.glGetError());
}
log.fine(() -> "OpenGL error code before loop: " + GL11.glGetError());
while (!GLFW.glfwWindowShouldClose(windowId)) {
/* Do something */
GL30.glClearBufferfv(GL11.GL_COLOR, 0, clearColor);
......@@ -359,44 +368,74 @@ public class CityGMLViewer {
CityGMLParser.parseEpsgCodeFromFile(file, config);
CityGMLContext context = CityGMLContext.newInstance();
CityGMLInputFactory in = context.createCityGMLInputFactory()
.withChunking(ChunkingOptions.chunkByCityModelMembers());
.withChunking(ChunkOptions.chunkByProperties(chunkProperties).skipCityModel(true));
try (ObservedInputStream ois = new ObservedInputStream(file);
CityGMLReader reader = in.createCityGMLReader(file.getAbsolutePath(), ois)) {
ois.addListener(p -> bar.drawProgress((int) (p * 82)));
FeatureMapper mapper = new FeatureMapper(config);
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
List<Future<FeatureMapper>> mappers = new ArrayList<>();
while (reader.hasNext()) {
AbstractFeature chunk = reader.next();
if (chunk instanceof AbstractCityObject) {
AbstractCityObject aco = (AbstractCityObject) chunk;
aco.accept(mapper);
}
CityGMLChunk nextChunk = reader.nextChunk();
mappers.add(service.submit(() -> {
FeatureMapper mapper = new FeatureMapper(config);
AbstractFeature feature = nextChunk.build();
feature.accept(mapper);
return mapper;
}));
}
BoundingBox bbox = BoundingBox.of(mapper);
service.shutdown();
service.awaitTermination(20, TimeUnit.MINUTES);
List<Polygon> lod1Polygons = new ArrayList<>();
List<Polygon> lod2Polygons = new ArrayList<>();
List<Polygon> lod3Polygons = new ArrayList<>();
List<Polygon> lod4Polygons = new ArrayList<>();
List<FeatureMapper> fMappers = mappers.stream().map(t -> {
try {
return t.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.severe("Could not finish parsing file in 20 minutes, aborting");
throw new IllegalStateException(e);
} catch (ExecutionException e) {
log.severe("Could not parsing file completely, cause: " + e.getCause().getMessage());
throw new IllegalStateException(e);
}
}).toList();
fMappers.stream().forEach(m -> {
lod1Polygons.addAll(m.getLod1Polygons());
lod2Polygons.addAll(m.getLod2Polygons());
lod3Polygons.addAll(m.getLod3Polygons());
lod4Polygons.addAll(m.getLod4Polygons());
});
BoundingBox bbox = BoundingBox.of(lod1Polygons, lod2Polygons, lod3Polygons, lod4Polygons);
bar.drawProgress(81);
Vector3d center = bbox.getCenter();
mapper.movePolygonsBy(center);
fMappers.forEach(m -> m.movePolygonsBy(center));
bar.drawProgress(82);
long nrOfPolygons = (long) mapper.getLod1Polygons().size() + mapper.getLod2Polygons().size()
+ mapper.getLod3Polygons().size() + mapper.getLod4Polygons().size();
long nrOfPolygons = (long) lod1Polygons.size() + lod2Polygons.size()
+ lod3Polygons.size() + lod4Polygons.size();
long[] count = new long[1];
log.info(() -> "Found " + nrOfPolygons + " polygons");
PolygonListener l = () -> {
count[0]++;
bar.drawProgress(82 + (int) (count[0] * 9 / nrOfPolygons));
};
if (!mapper.getLod1Polygons().isEmpty()) {
PolygonViewInformation lod1ViewInfo = new PolygonViewInformation(mapper.getLod1Polygons(), l);
if (!lod1Polygons.isEmpty()) {
PolygonViewInformation lod1ViewInfo = new PolygonViewInformation(lod1Polygons, l);
viewing.add(lod1ViewInfo);
}
if (!mapper.getLod2Polygons().isEmpty()) {
PolygonViewInformation lod2ViewInfo = new PolygonViewInformation(mapper.getLod2Polygons(), l);
if (!lod2Polygons.isEmpty()) {
PolygonViewInformation lod2ViewInfo = new PolygonViewInformation(lod2Polygons, l);
viewing.add(lod2ViewInfo);
}
if (!mapper.getLod3Polygons().isEmpty()) {
PolygonViewInformation lod3ViewInfo = new PolygonViewInformation(mapper.getLod3Polygons(), l);
if (!lod3Polygons.isEmpty()) {
PolygonViewInformation lod3ViewInfo = new PolygonViewInformation(lod3Polygons, l);
viewing.add(lod3ViewInfo);
}
if (!mapper.getLod3Polygons().isEmpty()) {
PolygonViewInformation lod4ViewInfo = new PolygonViewInformation(mapper.getLod4Polygons(), l);
if (!lod4Polygons.isEmpty()) {
PolygonViewInformation lod4ViewInfo = new PolygonViewInformation(lod4Polygons, l);
viewing.add(lod4ViewInfo);
}
......@@ -406,6 +445,9 @@ public class CityGMLViewer {
camera.setDistance((float) translateZ);
cameraViewDistance = (float) longestSide * 20f;
camera.reshape(width, height, cameraViewDistance);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.severe("Could not finish parsing file in 20 minutes, aborting");
}
} catch (GLException | IOException | ParserConfigurationException | SAXException | CityGMLContextException
| CityGMLReadException e) {
......
......@@ -26,12 +26,10 @@ import java.util.List;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL44;
import org.lwjgl.opengl.GL45;
import org.lwjgl.system.MemoryUtil;
import de.hft.stuttgart.citygml.viewer.datastructure.BufferConstants;
import de.hft.stuttgart.citygml.viewer.datastructure.Polygon;
import de.hft.stuttgart.citygml.viewer.datastructure.TesselatedPolygon;
import de.hft.stuttgart.citygml.viewer.datastructure.Triangle3d;
......@@ -41,34 +39,37 @@ public class PolygonViewInformation {
private static final Vector3d AXIS = new Vector3d(19, 0.8, 1.5).normalize();
private int vao;
private IntBuffer buffers;
private boolean draw = false;
private int elements;
private PolygonListener listener;
private int posVbo;
private int colorVbo;
private int indexVbo;
public PolygonViewInformation(List<Polygon> polygons, PolygonListener listener) {
this.listener = listener;
vao = GL45.glCreateVertexArrays();
GL45.glVertexArrayAttribBinding(vao, BufferConstants.ATTRIBUTE_POSITION, BufferConstants.BINDING_INDEX_0);
GL45.glVertexArrayAttribBinding(vao, BufferConstants.ATTRIBUTE_COLOR, BufferConstants.BINDING_INDEX_0);
GL45.glVertexArrayAttribFormat(vao, BufferConstants.ATTRIBUTE_POSITION, 3, GL_FLOAT, false, 0);
GL45.glVertexArrayAttribFormat(vao, BufferConstants.ATTRIBUTE_COLOR, 3, GL_FLOAT, false, 3 * 4);
GL45.glEnableVertexArrayAttrib(vao, BufferConstants.ATTRIBUTE_POSITION);
GL45.glEnableVertexArrayAttrib(vao, BufferConstants.ATTRIBUTE_COLOR);
buffers = MemoryUtil.memAllocInt(BufferConstants.SIZE);
GL45.glCreateBuffers(buffers);
GL45.glVertexArrayElementBuffer(vao, buffers.get(BufferConstants.ELEMENT));
GL45.glVertexArrayVertexBuffer(vao, BufferConstants.BINDING_INDEX_0, buffers.get(BufferConstants.VERTEX), 0, (3 + 3) * 4);
setupBuffers(polygons);
vao = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao);
posVbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, posVbo);
GL20.glEnableVertexAttribArray(0);
GL20.glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
colorVbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorVbo);
GL20.glEnableVertexAttribArray(1);
GL20.glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
indexVbo = GL15.glGenBuffers();
setupBuffers(polygons, posVbo, colorVbo, indexVbo);
GL30.glBindVertexArray(0);
}
private void setupBuffers(List<Polygon> polys) {
private void setupBuffers(List<Polygon> polys, int posVbo, int colorVbo, int indexVbo) {
List<TesselatedPolygon> tessPolys = new ArrayList<>();
for (Polygon poly : polys) {
tessPolys.add(TesselatedPolygon.of(poly));
......@@ -81,8 +82,11 @@ public class PolygonViewInformation {
}
// 6 float for 3 vertices per triangle
int moreSpace = nrOfTriangles * 3 * 3 * 2;
FloatBuffer vertexData = MemoryUtil.memAllocFloat(moreSpace);
int vertexDataSize = nrOfTriangles * 3 * 3;
FloatBuffer vertexData = MemoryUtil.memAllocFloat(vertexDataSize);
int colorDataSize = nrOfTriangles * 3 * 3;
FloatBuffer colorData = MemoryUtil.memAllocFloat(colorDataSize);
IntBuffer elementData = MemoryUtil.memAllocInt(nrOfTriangles * 3);
float[] rgba = new float[4];
for (TesselatedPolygon tessPoly : tessPolys) {
......@@ -96,9 +100,9 @@ public class PolygonViewInformation {
(int) (baseColor.getBlue() * acos));
derivedColor.getComponents(rgba);
for (Triangle3d tri : tessPoly.getTriangles()) {
addPoint(vertexData, tri.getP1(), rgba[0], rgba[1], rgba[2]);
addPoint(vertexData, tri.getP2(), rgba[0], rgba[1], rgba[2]);
addPoint(vertexData, tri.getP3(), rgba[0], rgba[1], rgba[2]);
addPoint(vertexData, colorData, tri.getP1(), rgba[0], rgba[1], rgba[2]);
addPoint(vertexData, colorData, tri.getP2(), rgba[0], rgba[1], rgba[2]);
addPoint(vertexData, colorData, tri.getP3(), rgba[0], rgba[1], rgba[2]);
}
listener.finishedPolygon();
}
......@@ -106,30 +110,35 @@ public class PolygonViewInformation {
elementData.put(i);
}
((Buffer) elementData).flip();
((Buffer) colorData).flip();
((Buffer) vertexData).flip();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buffers.get(BufferConstants.VERTEX));
GL44.glBufferStorage(GL15.GL_ARRAY_BUFFER, vertexData, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, posVbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexData, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorVbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorData, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, buffers.get(BufferConstants.ELEMENT));
GL44.glBufferStorage(GL15.GL_ELEMENT_ARRAY_BUFFER, elementData, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexVbo);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, elementData, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
MemoryUtil.memFree(elementData);
MemoryUtil.memFree(colorData);
MemoryUtil.memFree(vertexData);
draw = true;
elements = elementData.capacity();
}
private static void addPoint(FloatBuffer lod1VertexData, Vector3d point, float red, float green, float blue) {
lod1VertexData.put((float) point.getX());
lod1VertexData.put((float) point.getY());
lod1VertexData.put((float) point.getZ());
lod1VertexData.put(red);
lod1VertexData.put(green);
lod1VertexData.put(blue);
private static void addPoint(FloatBuffer vertexData, FloatBuffer colorData, Vector3d point, float red, float green, float blue) {
vertexData.put((float) point.getX());
vertexData.put((float) point.getY());
vertexData.put((float) point.getZ());
colorData.put(red);
colorData.put(green);
colorData.put(blue);
}
public boolean shouldDraw() {
......@@ -145,13 +154,16 @@ public class PolygonViewInformation {
}
public void destroy() {
MemoryUtil.memFree(buffers);
GL15.glDeleteBuffers(colorVbo);
GL15.glDeleteBuffers(posVbo);
GL15.glDeleteBuffers(indexVbo);
GL30.glDeleteVertexArrays(vao);
}
public void draw() {
if (draw) {
GL30.glBindVertexArray(vao);
GL11.glDrawElements(GL11.GL_TRIANGLES, elements, GL11.GL_UNSIGNED_INT, 0);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, elements);
}
}
}
......@@ -162,4 +162,10 @@ public class BoundingBox {
public String toString() {
return Arrays.toString(bbox);
}
public static BoundingBox of(List<Polygon> lod1Polygons, List<Polygon> lod2Polygons, List<Polygon> lod3Polygons,
List<Polygon> lod4Polygons) {
return BoundingBoxCalculator.calculateBoundingBox(lod1Polygons, lod2Polygons, lod3Polygons, lod4Polygons);
}
}
......@@ -116,11 +116,16 @@ public class BoundingBoxCalculator {
}
public static BoundingBox calculateBoundingBox(FeatureMapper mapper) {
return calculateBoundingBox(mapper.getLod1Polygons(), mapper.getLod2Polygons(), mapper.getLod3Polygons(), mapper.getLod4Polygons());
}
public static BoundingBox calculateBoundingBox(List<Polygon> lod1Polygons, List<Polygon> lod2Polygons,
List<Polygon> lod3Polygons, List<Polygon> lod4Polygons) {
List<List<Polygon>> polygonList = new ArrayList<>();
polygonList.add(mapper.getLod1Polygons());
polygonList.add(mapper.getLod2Polygons());
polygonList.add(mapper.getLod3Polygons());
polygonList.add(mapper.getLod4Polygons());
polygonList.add(lod1Polygons);
polygonList.add(lod2Polygons);
polygonList.add(lod3Polygons);
polygonList.add(lod4Polygons);
double lowX = Double.MAX_VALUE;
double highX = Double.NEGATIVE_INFINITY;
......
package de.hft.stuttgart.citygml.viewer.parser;
import java.awt.Color;
import java.io.FileReader;
import java.util.Properties;
import java.util.logging.Logger;
public class ColorHandler {
private static final Logger logger = Logger.getLogger(ColorHandler.class.getName());
private static Color groundColor = new Color(0.9411765f, 0.9019608f, 0.54901963f);
private static Color roofColor = Color.RED;
private static Color doorColor = Color.ORANGE;
private static Color windowColor = new Color(0.0f, 0.5019608f, 0.5019608f);
private static Color wallColor = Color.WHITE;
private static Color bridgeColor = new Color(1.0f, 0.49803922f, 0.3137255f);
private static Color landColor = new Color(0.64705884f, 0.16470589f, 0.16470589f);
private static Color transportationColor = new Color(1.0f, 1.0f, 0.0f);
private static Color vegetationColor = new Color(0.5647059f, 0.93333334f, 0.5647059f);
private static Color waterColor = new Color(0.5294118f, 0.80784315f, 0.98039216f);
static {
try (FileReader reader = new FileReader("color.properties")) {
Properties props = new Properties();
props.load(reader);
Color parsedGroundColor = parseColor(props.getProperty("groundColor"));
if (parsedGroundColor != null) {
groundColor = parsedGroundColor;
}
Color parsedRoofColor = parseColor(props.getProperty("roofColor"));
if (parsedRoofColor != null) {
roofColor = parsedRoofColor;
}
Color parsedDoorColor = parseColor(props.getProperty("doorColor"));
if (parsedDoorColor != null) {
doorColor = parsedDoorColor;
}
Color parsedWindowColor = parseColor(props.getProperty("windowColor"));
if (parsedWindowColor != null) {
windowColor = parsedWindowColor;
}
Color parsedWallColor = parseColor(props.getProperty("wallColor"));
if (parsedWallColor != null) {
wallColor = parsedWallColor;
}
Color parsedBridgeColor = parseColor(props.getProperty("bridgeColor"));
if (parsedBridgeColor != null) {
bridgeColor = parsedBridgeColor;
}
Color parsedLandColor = parseColor(props.getProperty("landColor"));
if (parsedLandColor != null) {
landColor = parsedLandColor;
}
Color parsedTransportationColor = parseColor(props.getProperty("transportationColor"));
if (parsedTransportationColor != null) {
transportationColor = parsedTransportationColor;
}
Color parsedVegetationColor = parseColor(props.getProperty("vegetationColor"));
if (parsedVegetationColor != null) {
vegetationColor = parsedVegetationColor;
}
Color parsedWaterColor = parseColor(props.getProperty("waterColor"));
if (parsedWaterColor != null) {
waterColor = parsedWaterColor;
}
}catch (Exception e) {
logger.warning(() -> "Failed to read color properties file: " + e.getMessage());
}
}
private ColorHandler() {
}
private static Color parseColor(String colorString) {
if (colorString == null) {
return null;
}
try {
String[] split = colorString.split(" ");
float r = Float.parseFloat(split[0]);
float g = Float.parseFloat(split[1]);
float b = Float.parseFloat(split[2]);
return new Color(r, g, b);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Color getGroundColor() {
return groundColor;
}
public static Color getRoofColor() {
return roofColor;
}
public static Color getDoorColor() {
return doorColor;
}
public static Color getWindowColor() {
return windowColor;
}
public static Color getWallColor() {
return wallColor;
}
public static Color getBridgeColor() {
return bridgeColor;
}
public static Color getLandColor() {
return landColor;
}
public static Color getTransportationColor() {
return transportationColor;
}
public static Color getVegetationColor() {
return vegetationColor;
}
public static Color getWaterColor() {
return waterColor;
}
}
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