package org.osm2world.core.target.povray;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Locale;
import org.osm2world.core.GlobalValues;
import org.osm2world.core.map_data.data.MapData;
import org.osm2world.core.map_data.data.MapElement;
import org.osm2world.core.math.VectorXYZ;
import org.osm2world.core.target.TargetUtil;
import org.osm2world.core.target.common.lighting.GlobalLightingParameters;
import org.osm2world.core.target.common.rendering.Camera;
import org.osm2world.core.target.common.rendering.Projection;
import org.osm2world.core.world.data.WorldObject;
/**
* utility class for creating a POVRay file
*/
public final class POVRayWriter {
/** prevents instantiation */
private POVRayWriter() { }
public static final void writePOVInstructionFile(File file, MapData mapData,
Camera camera, Projection projection)
throws IOException {
if (!file.exists()) {
file.createNewFile();
}
PrintStream printStream = new PrintStream(file);
writePOVInstructionStringToStream(printStream,
mapData, camera, projection);
printStream.close();
}
private static final void writePOVInstructionStringToStream(
PrintStream stream, MapData mapData,
Camera camera, Projection projection) {
POVRayTarget target = new POVRayTarget(stream);
addCommentHeader(target);
target.append("\n#include \"textures.inc\"\n#include \"colors.inc\"\n");
target.append("#include \"osm2world_definitions.inc\"\n\n");
if (camera != null && projection != null) {
addCameraDefinition(target, camera, projection);
}
target.append("//\n// global scene parameters\n//\n\n");
addLightingDefinition(target, GlobalLightingParameters.DEFAULT);
target.appendDefaultParameterValue("season", "summer");
target.appendDefaultParameterValue("time", "day");
target.append("//\n// material and object definitions\n//\n\n");
target.appendDefaultParameterValue("sky_sphere_def",
"sky_sphere {\n pigment { Blue_Sky3 }\n} ");
target.append("sky_sphere {sky_sphere_def}\n\n");
target.appendMaterialDefinitions();
for (MapElement element : mapData.getMapElements()) {
for (WorldObject r : element.getRepresentations()) {
if (r instanceof RenderableToPOVRay) {
((RenderableToPOVRay)r).addDeclarationsTo(target);
}
}
}
//TODO get terrain boundary elsewhere
// if (terrain != null) {
//
// target.append("//\n// empty ground around the scene\n//\n\n");
//
// target.append("difference {\n");
// target.append(" plane { y, -0.001 }\n ");
// VectorXZ[] boundary = eleData.getBoundaryPolygon().getXZPolygon()
// .getVertexLoop().toArray(new VectorXZ[0]);
// target.appendPrism( -100, 1, boundary);
// target.append("\n");
// target.appendMaterialOrName(Materials.TERRAIN_DEFAULT);
// target.append("\n}\n\n");
//
// }
target.append("\n\n//\n//Map data\n//\n\n");
TargetUtil.renderWorldObjects(target, mapData, true);
}
private static final void addLightingDefinition(POVRayTarget target,
GlobalLightingParameters parameters) {
target.append(String.format(Locale.ENGLISH,
"global_settings { ambient_light rgb <%f,%f,%f> }\n",
parameters.globalAmbientColor.getRed() / 255f,
parameters.globalAmbientColor.getGreen() / 255f,
parameters.globalAmbientColor.getBlue() / 255f));
target.append(String.format(Locale.ENGLISH,
"light_source{ <%f,%f,%f> color rgb <%f,%f,%f> parallel point_at <0,0,0> fade_power 0 }\n\n",
parameters.lightFromDirection.x * 100000,
parameters.lightFromDirection.y * 100000,
parameters.lightFromDirection.z * 100000,
parameters.lightColorDiffuse.getRed() / 255f,
parameters.lightColorDiffuse.getGreen() / 255f,
parameters.lightColorDiffuse.getBlue() / 255f));
}
private static final void addCommentHeader(POVRayTarget target) {
target.append("/*\n"
+ " * This file was created by OSM2World "
+ GlobalValues.VERSION_STRING + " - "
+ GlobalValues.OSM2WORLD_URI + "\n"
+ " * \n"
+ " * Make sure that a \"osm2world_definitions.inc\" file exists!\n"
+ " * You can start with the one in the \"resources\" folder from your\n"
+ " * OSM2World installation or even just create an empty file.\n"
+ " */\n");
}
private static final void addCameraDefinition(POVRayTarget target,
Camera camera, Projection projection) {
target.append("camera {");
if (projection.isOrthographic()) {
target.append("\n orthographic");
}
target.append("\n location ");
target.appendVector(camera.getPos());
if (projection.isOrthographic()) {
target.append("\n right ");
double width = projection.getVolumeHeight()
* projection.getAspectRatio();
target.appendVector(camera.getRight().mult(width).invert()); //invert compensates for left-handed vs. right handed coordinates
target.append("\n up ");
VectorXYZ up = camera.getUp();
target.appendVector(up.mult(projection.getVolumeHeight()));
target.append("\n look_at ");
target.appendVector(camera.getLookAt());
} else {
target.append("\n look_at ");
target.appendVector(camera.getLookAt());
target.append("\n sky ");
target.appendVector(camera.getUp());
}
target.append("\n}\n\n");
}
}