package org.osm2world.core.target.obj;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Iterator;
import org.osm2world.core.GlobalValues;
import org.osm2world.core.map_data.creation.MapProjection;
import org.osm2world.core.map_data.data.MapData;
import org.osm2world.core.math.VectorXYZ;
import org.osm2world.core.math.VectorXZ;
import org.osm2world.core.target.TargetUtil;
import org.osm2world.core.target.common.rendering.Camera;
import org.osm2world.core.target.common.rendering.Projection;
/**
* utility class for creating an Wavefront OBJ file
*/
public final class ObjWriter {
/** prevents instantiation */
private ObjWriter() { }
public static final void writeObjFile(
File objFile, MapData mapData,
MapProjection mapProjection,
Camera camera, Projection projection)
throws IOException {
if (!objFile.exists()) {
objFile.createNewFile();
}
File mtlFile = new File(objFile.getAbsoluteFile() + ".mtl");
if (!mtlFile.exists()) {
mtlFile.createNewFile();
}
PrintStream objStream = new PrintStream(objFile);
PrintStream mtlStream = new PrintStream(mtlFile);
/* write comments at the beginning of both files */
writeObjHeader(objStream, mapProjection);
writeMtlHeader(mtlStream);
/* write path of mtl file to obj file */
objStream.println("mtllib " + mtlFile.getName() + "\n");
/* write actual file content */
ObjTarget target = new ObjTarget(objStream, mtlStream);
TargetUtil.renderWorldObjects(target, mapData, true);
objStream.close();
mtlStream.close();
}
public static final void writeObjFiles(
final File objDirectory, MapData mapData,
final MapProjection mapProjection,
Camera camera, Projection projection,
int primitiveThresholdPerFile)
throws IOException {
if (!objDirectory.exists()) {
objDirectory.mkdir();
}
checkArgument(objDirectory.isDirectory());
final File mtlFile = new File(objDirectory.getPath()
+ File.separator + "materials.mtl");
if (!mtlFile.exists()) {
mtlFile.createNewFile();
}
final PrintStream mtlStream = new PrintStream(mtlFile);
writeMtlHeader(mtlStream);
/* create iterator which creates and wraps .obj files as needed */
Iterator<ObjTarget> objIterator = new Iterator<ObjTarget>() {
private int fileCounter = 0;
PrintStream objStream = null;
@Override
public boolean hasNext() {
return true;
}
@Override
public ObjTarget next() {
try {
if (objStream != null) {
objStream.close();
fileCounter ++;
}
File objFile = new File(objDirectory.getPath() + File.separator
+ "part" + format("%04d", fileCounter) + ".obj");
if (!objFile.exists()) {
objFile.createNewFile();
}
objStream = new PrintStream(objFile);
writeObjHeader(objStream, mapProjection);
objStream.println("mtllib " + mtlFile.getName() + "\n");
return new ObjTarget(objStream, mtlStream);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
/* write file content */
TargetUtil.renderWorldObjects(objIterator, mapData, primitiveThresholdPerFile);
mtlStream.close();
}
private static final void writeObjHeader(PrintStream objStream,
MapProjection mapProjection) {
objStream.println("# This file was created by OSM2World "
+ GlobalValues.VERSION_STRING + " - "
+ GlobalValues.OSM2WORLD_URI + "\n");
objStream.println("# Projection information:");
objStream.println("# Coordinate origin (0,0,0): "
+ "lat " + mapProjection.calcLat(VectorXZ.NULL_VECTOR) + ", "
+ "lon " + mapProjection.calcLon(VectorXZ.NULL_VECTOR) + ", "
+ "ele 0");
objStream.println("# North direction: " + new VectorXYZ(
mapProjection.getNorthUnit().x, 0,
- mapProjection.getNorthUnit().z));
objStream.println("# 1 coordinate unit corresponds to roughly "
+ "1 m in reality\n");
}
private static final void writeMtlHeader(PrintStream mtlStream) {
mtlStream.println("# This file was created by OSM2World "
+ GlobalValues.VERSION_STRING + " - "
+ GlobalValues.OSM2WORLD_URI + "\n");
}
}