use of org.sunflow.util.IntArray in project joons-renderer by joonhyublee.
the class FileMesh method tesselate.
public PrimitiveList tesselate() {
if (filename.endsWith(".ra3")) {
try {
UI.printInfo(Module.GEOM, "RA3 - Reading geometry: \"%s\" ...", filename);
File file = new File(filename);
FileInputStream stream = new FileInputStream(filename);
MappedByteBuffer map = stream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
map.order(ByteOrder.LITTLE_ENDIAN);
IntBuffer ints = map.asIntBuffer();
FloatBuffer buffer = map.asFloatBuffer();
int numVerts = ints.get(0);
int numTris = ints.get(1);
UI.printInfo(Module.GEOM, "RA3 - * Reading %d vertices ...", numVerts);
float[] verts = new float[3 * numVerts];
for (int i = 0; i < verts.length; i++) {
verts[i] = buffer.get(2 + i);
}
UI.printInfo(Module.GEOM, "RA3 - * Reading %d triangles ...", numTris);
int[] tris = new int[3 * numTris];
for (int i = 0; i < tris.length; i++) {
tris[i] = ints.get(2 + verts.length + i);
}
stream.close();
UI.printInfo(Module.GEOM, "RA3 - * Creating mesh ...");
return generate(tris, verts, smoothNormals);
} catch (FileNotFoundException e) {
Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - file not found", filename);
} catch (IOException e) {
Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - I/O error occured", filename);
}
} else if (filename.endsWith(".obj")) {
int lineNumber = 1;
try {
UI.printInfo(Module.GEOM, "OBJ - Reading geometry: \"%s\" ...", filename);
FloatArray verts = new FloatArray();
IntArray tris = new IntArray();
FileReader file = new FileReader(filename);
BufferedReader bf = new BufferedReader(file);
String line;
while ((line = bf.readLine()) != null) {
if (line.startsWith("v")) {
String[] v = line.split("\\s+");
verts.add(Float.parseFloat(v[1]));
verts.add(Float.parseFloat(v[2]));
verts.add(Float.parseFloat(v[3]));
} else if (line.startsWith("f")) {
String[] f = line.split("\\s+");
if (f.length == 5) {
tris.add(Integer.parseInt(f[1]) - 1);
tris.add(Integer.parseInt(f[2]) - 1);
tris.add(Integer.parseInt(f[3]) - 1);
tris.add(Integer.parseInt(f[1]) - 1);
tris.add(Integer.parseInt(f[3]) - 1);
tris.add(Integer.parseInt(f[4]) - 1);
} else if (f.length == 4) {
tris.add(Integer.parseInt(f[1]) - 1);
tris.add(Integer.parseInt(f[2]) - 1);
tris.add(Integer.parseInt(f[3]) - 1);
}
}
if (lineNumber % 100000 == 0) {
UI.printInfo(Module.GEOM, "OBJ - * Parsed %7d lines ...", lineNumber);
}
lineNumber++;
}
file.close();
UI.printInfo(Module.GEOM, "OBJ - * Creating mesh ...");
return generate(tris.trim(), verts.trim(), smoothNormals);
} catch (FileNotFoundException e) {
Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - file not found", filename);
} catch (NumberFormatException e) {
Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - syntax error at line %d", lineNumber);
} catch (IOException e) {
Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - I/O error occured", filename);
}
} else if (filename.endsWith(".stl")) {
try {
UI.printInfo(Module.GEOM, "STL - Reading geometry: \"%s\" ...", filename);
FileInputStream file = new FileInputStream(filename);
DataInputStream stream = new DataInputStream(new BufferedInputStream(file));
file.skip(80);
int numTris = getLittleEndianInt(stream.readInt());
UI.printInfo(Module.GEOM, "STL - * Reading %d triangles ...", numTris);
long filesize = new File(filename).length();
if (filesize != (84 + 50 * numTris)) {
UI.printWarning(Module.GEOM, "STL - Size of file mismatch (expecting %s, found %s)", Memory.bytesToString(84 + 14 * numTris), Memory.bytesToString(filesize));
return null;
}
int[] tris = new int[3 * numTris];
float[] verts = new float[9 * numTris];
for (int i = 0, i3 = 0, index = 0; i < numTris; i++, i3 += 3) {
// skip normal
stream.readInt();
stream.readInt();
stream.readInt();
for (int j = 0; j < 3; j++, index += 3) {
tris[i3 + j] = i3 + j;
// get xyz
verts[index + 0] = getLittleEndianFloat(stream.readInt());
verts[index + 1] = getLittleEndianFloat(stream.readInt());
verts[index + 2] = getLittleEndianFloat(stream.readInt());
}
stream.readShort();
if ((i + 1) % 100000 == 0) {
UI.printInfo(Module.GEOM, "STL - * Parsed %7d triangles ...", i + 1);
}
}
file.close();
// create geometry
UI.printInfo(Module.GEOM, "STL - * Creating mesh ...");
if (smoothNormals) {
UI.printWarning(Module.GEOM, "STL - format does not support shared vertices - normal smoothing disabled");
}
return generate(tris, verts, false);
} catch (FileNotFoundException e) {
Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - file not found", filename);
} catch (IOException e) {
Logger.getLogger(FileMesh.class.getName()).log(Level.SEVERE, null, e);
UI.printError(Module.GEOM, "Unable to read mesh file \"%s\" - I/O error occured", filename);
}
} else {
UI.printWarning(Module.GEOM, "Unable to read mesh file \"%s\" - unrecognized format", filename);
}
return null;
}
use of org.sunflow.util.IntArray in project joons-renderer by joonhyublee.
the class ShaveRibParser method parseIntArray.
private int[] parseIntArray(Parser p) throws IOException {
IntArray array = new IntArray();
boolean done = false;
do {
String s = p.getNextToken();
if (s.startsWith("[")) {
s = s.substring(1);
}
if (s.endsWith("]")) {
s = s.substring(0, s.length() - 1);
done = true;
}
array.add(Integer.parseInt(s));
} while (!done);
return array.trim();
}
use of org.sunflow.util.IntArray in project joons-renderer by joonhyublee.
the class KDTree method build.
@Override
public void build(PrimitiveList primitives) {
UI.printDetailed(Module.ACCEL, "KDTree settings");
UI.printDetailed(Module.ACCEL, " * Max Leaf Size: %d", maxPrims);
UI.printDetailed(Module.ACCEL, " * Max Depth: %d", MAX_DEPTH);
UI.printDetailed(Module.ACCEL, " * Traversal cost: %.2f", TRAVERSAL_COST);
UI.printDetailed(Module.ACCEL, " * Intersect cost: %.2f", INTERSECT_COST);
UI.printDetailed(Module.ACCEL, " * Empty bonus: %.2f", EMPTY_BONUS);
UI.printDetailed(Module.ACCEL, " * Dump leaves: %s", dump ? "enabled" : "disabled");
Timer total = new Timer();
total.start();
primitiveList = primitives;
// get the object space bounds
bounds = primitives.getWorldBounds(null);
int nPrim = primitiveList.getNumPrimitives(), nSplits = 0;
BuildTask task = new BuildTask(nPrim);
Timer prepare = new Timer();
prepare.start();
for (int i = 0; i < nPrim; i++) {
for (int axis = 0; axis < 3; axis++) {
float ls = primitiveList.getPrimitiveBound(i, 2 * axis + 0);
float rs = primitiveList.getPrimitiveBound(i, 2 * axis + 1);
if (ls == rs) {
// flat in this dimension
task.splits[nSplits] = pack(ls, PLANAR, axis, i);
nSplits++;
} else {
task.splits[nSplits + 0] = pack(ls, OPENED, axis, i);
task.splits[nSplits + 1] = pack(rs, CLOSED, axis, i);
nSplits += 2;
}
}
}
task.n = nSplits;
prepare.end();
Timer t = new Timer();
IntArray tempTree = new IntArray();
IntArray tempList = new IntArray();
tempTree.add(0);
tempTree.add(1);
t.start();
// sort it
Timer sorting = new Timer();
sorting.start();
radix12(task.splits, task.n);
sorting.end();
// build the actual tree
BuildStats stats = new BuildStats();
buildTree(bounds.getMinimum().x, bounds.getMaximum().x, bounds.getMinimum().y, bounds.getMaximum().y, bounds.getMinimum().z, bounds.getMaximum().z, task, 1, tempTree, 0, tempList, stats);
t.end();
// write out final arrays
// free some memory
task = null;
tree = tempTree.trim();
tempTree = null;
this.primitives = tempList.trim();
tempList = null;
total.end();
// display some extra info
stats.printStats();
UI.printDetailed(Module.ACCEL, " * Node memory: %s", Memory.sizeof(tree));
UI.printDetailed(Module.ACCEL, " * Object memory: %s", Memory.sizeof(this.primitives));
UI.printDetailed(Module.ACCEL, " * Prepare time: %s", prepare);
UI.printDetailed(Module.ACCEL, " * Sorting time: %s", sorting);
UI.printDetailed(Module.ACCEL, " * Tree creation: %s", t);
UI.printDetailed(Module.ACCEL, " * Build time: %s", total);
if (dump) {
try {
UI.printInfo(Module.ACCEL, "Dumping mtls to %s.mtl ...", dumpPrefix);
FileWriter mtlFile = new FileWriter(dumpPrefix + ".mtl");
int maxN = stats.maxObjects;
for (int n = 0; n <= maxN; n++) {
float blend = (float) n / (float) maxN;
Color nc;
if (blend < 0.25) {
nc = Color.blend(Color.BLUE, Color.GREEN, blend / 0.25f);
} else if (blend < 0.5) {
nc = Color.blend(Color.GREEN, Color.YELLOW, (blend - 0.25f) / 0.25f);
} else if (blend < 0.75) {
nc = Color.blend(Color.YELLOW, Color.RED, (blend - 0.50f) / 0.25f);
} else {
nc = Color.MAGENTA;
}
mtlFile.write(String.format("newmtl mtl%d\n", n));
float[] rgb = nc.getRGB();
mtlFile.write("Ka 0.1 0.1 0.1\n");
mtlFile.write(String.format("Kd %.12g %.12g %.12g\n", rgb[0], rgb[1], rgb[2]));
mtlFile.write("illum 1\n\n");
}
FileWriter objFile = new FileWriter(dumpPrefix + ".obj");
UI.printInfo(Module.ACCEL, "Dumping tree to %s.obj ...", dumpPrefix);
dumpObj(0, 0, maxN, new BoundingBox(bounds), objFile, mtlFile);
objFile.close();
mtlFile.close();
} catch (IOException e) {
Logger.getLogger(KDTree.class.getName()).log(Level.SEVERE, null, e);
}
}
}
use of org.sunflow.util.IntArray in project joons-renderer by joonhyublee.
the class UniformGrid method build.
@Override
public void build(PrimitiveList primitives) {
Timer t = new Timer();
t.start();
this.primitives = primitives;
int n = primitives.getNumPrimitives();
// compute bounds
bounds = primitives.getWorldBounds(null);
// create grid from number of objects
bounds.enlargeUlps();
Vector3 w = bounds.getExtents();
double s = Math.pow((w.x * w.y * w.z) / n, 1 / 3.0);
nx = MathUtils.clamp((int) ((w.x / s) + 0.5), 1, 128);
ny = MathUtils.clamp((int) ((w.y / s) + 0.5), 1, 128);
nz = MathUtils.clamp((int) ((w.z / s) + 0.5), 1, 128);
voxelwx = w.x / nx;
voxelwy = w.y / ny;
voxelwz = w.z / nz;
invVoxelwx = 1 / voxelwx;
invVoxelwy = 1 / voxelwy;
invVoxelwz = 1 / voxelwz;
UI.printDetailed(Module.ACCEL, "Creating grid: %dx%dx%d ...", nx, ny, nz);
IntArray[] buildCells = new IntArray[nx * ny * nz];
// add all objects into the grid cells they overlap
int[] imin = new int[3];
int[] imax = new int[3];
int numCellsPerObject = 0;
for (int i = 0; i < n; i++) {
getGridIndex(primitives.getPrimitiveBound(i, 0), primitives.getPrimitiveBound(i, 2), primitives.getPrimitiveBound(i, 4), imin);
getGridIndex(primitives.getPrimitiveBound(i, 1), primitives.getPrimitiveBound(i, 3), primitives.getPrimitiveBound(i, 5), imax);
for (int ix = imin[0]; ix <= imax[0]; ix++) {
for (int iy = imin[1]; iy <= imax[1]; iy++) {
for (int iz = imin[2]; iz <= imax[2]; iz++) {
int idx = ix + (nx * iy) + (nx * ny * iz);
if (buildCells[idx] == null) {
buildCells[idx] = new IntArray();
}
buildCells[idx].add(i);
numCellsPerObject++;
}
}
}
}
UI.printDetailed(Module.ACCEL, "Building cells ...");
int numEmpty = 0;
int numInFull = 0;
cells = new int[nx * ny * nz][];
int i = 0;
for (IntArray cell : buildCells) {
if (cell != null) {
if (cell.getSize() == 0) {
numEmpty++;
cell = null;
} else {
cells[i] = cell.trim();
numInFull += cell.getSize();
}
} else {
numEmpty++;
}
i++;
}
t.end();
UI.printDetailed(Module.ACCEL, "Uniform grid statistics:");
UI.printDetailed(Module.ACCEL, " * Grid cells: %d", cells.length);
UI.printDetailed(Module.ACCEL, " * Used cells: %d", cells.length - numEmpty);
UI.printDetailed(Module.ACCEL, " * Empty cells: %d", numEmpty);
UI.printDetailed(Module.ACCEL, " * Occupancy: %.2f%%", 100.0 * (cells.length - numEmpty) / cells.length);
UI.printDetailed(Module.ACCEL, " * Objects/Cell: %.2f", (double) numInFull / (double) cells.length);
UI.printDetailed(Module.ACCEL, " * Objects/Used Cell: %.2f", (double) numInFull / (double) (cells.length - numEmpty));
UI.printDetailed(Module.ACCEL, " * Cells/Object: %.2f", (double) numCellsPerObject / (double) n);
UI.printDetailed(Module.ACCEL, " * Build time: %s", t.toString());
}
use of org.sunflow.util.IntArray in project joons-renderer by joonhyublee.
the class BoundingIntervalHierarchy method build.
@Override
public void build(PrimitiveList primitives) {
this.primitives = primitives;
int n = primitives.getNumPrimitives();
UI.printDetailed(Module.ACCEL, "Getting bounding box ...");
bounds = primitives.getWorldBounds(null);
objects = new int[n];
for (int i = 0; i < n; i++) {
objects[i] = i;
}
UI.printDetailed(Module.ACCEL, "Creating tree ...");
int initialSize = 3 * (2 * 6 * n + 1);
IntArray tempTree = new IntArray((initialSize + 3) / 4);
BuildStats stats = new BuildStats();
Timer t = new Timer();
t.start();
buildHierarchy(tempTree, objects, stats);
t.end();
UI.printDetailed(Module.ACCEL, "Trimming tree ...");
tree = tempTree.trim();
// display stats
stats.printStats();
UI.printDetailed(Module.ACCEL, " * Creation time: %s", t);
UI.printDetailed(Module.ACCEL, " * Usage of init: %6.2f%%", (double) (100.0 * tree.length) / initialSize);
UI.printDetailed(Module.ACCEL, " * Tree memory: %s", Memory.sizeof(tree));
UI.printDetailed(Module.ACCEL, " * Indices memory: %s", Memory.sizeof(objects));
}
Aggregations