use of org.twak.utils.collections.CountThings in project chordatlas by twak.
the class ReadTrace method postProcessFrames.
private void postProcessFrames() throws Throwable {
ObjDump out = new ObjDump();
// start with data most likely to be loaded
Collections.reverse(frames);
double[] tmp = new double[4];
for (Frame f : frames) {
// filter out large tiles
CountThings<Double> lengths = new CountThings<>();
for (FrameGeometry fg : f) {
for (int i = 0; i < 3; i++) {
fg.viewMatrix.getColumn(i, tmp);
lengths.count((double) Math.round(new Vector4d(tmp).length() * 20) / 20);
}
}
// we assume the most popular tile size is the smallest (and that they've loaded)
double targetLength = lengths.getMax().first();
double t = 0.01 / targetLength;
Matrix4d scale = new Matrix4d(t, 0, 0, 0, 0, t, 0, 0, 0, 0, t, 0, 0, 0, 0, t);
Iterator<FrameGeometry> fig = f.iterator();
fig: while (fig.hasNext()) {
FrameGeometry fg = fig.next();
for (int i = 0; i < 3; i++) {
fg.viewMatrix.getColumn(i, tmp);
if (new Vector4d(tmp).lengthSquared() > (targetLength * targetLength * 1.01)) {
// remove non-smallest tile size
fig.remove();
continue fig;
}
}
fg.viewMatrix.mul(scale);
// y-up!
swapRows(fg.viewMatrix, 0, 1);
swapRows(fg.viewMatrix, 0, 2);
fg.viewMatrix.m33 = 1;
}
}
Matrix4d frameTransform = new Matrix4d();
frameTransform.setIdentity();
Map<String, Matrix4d> knownVerts = new HashMap<>();
Iterator<Frame> fit = frames.iterator();
while (fit.hasNext()) if (fit.next().size() < 50) {
System.out.println("warning: removing small frame");
fit.remove();
}
fit = frames.iterator();
while (fit.hasNext()) {
Frame f = fit.next();
Set<Matrix4d> mats = new HashSet<>();
for (FrameGeometry fg : f) {
if (knownVerts.containsKey(fg.loc)) {
Matrix4d toFrame = new Matrix4d(fg.viewMatrix);
toFrame.invert();
toFrame.mul(knownVerts.get(fg.loc));
mats.add(toFrame);
// frameTransform = new Matrix4d( fg.viewMatrix );
// frameTransform.invert();
// frameTransform.mul( knownVerts.get( fg.loc ) );
//
// break;
// frameTransform = toFrame;
}
}
if (!mats.isEmpty())
frameTransform = average(mats);
if (frameTransform != null) {
// apply found transform to all within same frame
Iterator<FrameGeometry> fig = f.iterator();
while (fig.hasNext()) {
FrameGeometry fg = fig.next();
if (knownVerts.containsKey(fg.loc)) {
fig.remove();
} else {
fg.viewMatrix.mul(frameTransform);
knownVerts.put(fg.loc, fg.viewMatrix);
}
}
} else {
System.out.println("failed to find origin for frame");
fit.remove();
}
frameTransform = null;
}
int count = 0, c2 = 0;
MiniTransform miniTransform = new MiniTransform();
for (Frame f : frames) {
// write out the frames into a single file
System.out.println("post-processing " + count++ + "/" + frames.size());
for (FrameGeometry fg : f) {
File miniFrameFolder = null;
File outFolder = folder;
Matrix4d meshTransform = fg.viewMatrix;
if (miniMesh != null) {
// if we're writing out in the miniMesh format
out = new ObjDump();
miniFrameFolder = new File(miniMesh, c2 + "");
miniFrameFolder.mkdirs();
miniTransform.index.put(c2, fg.viewMatrix);
outFolder = miniFrameFolder;
meshTransform = new Matrix4d();
meshTransform.setIdentity();
}
int[] ind = BitTwiddle.byteToUShort(getBytes(fg.ind));
if (ind == null) {
System.out.println("*** missing index buffer " + fg.ind);
continue;
}
byte[] vtLocBytes = getBytes(fg.loc);
if (vtLocBytes == null)
continue;
int[][] vtLoc = BitTwiddle.byteToUByte(vtLocBytes, 4, (int) fg.iVals[VERTEX_BUFFER_OFFSET], (int) fg.iVals[VERTEX_BUFFER_STRIDE]);
byte[] uvBytes = Files.readAllBytes(new File(folder, fg.uvs).toPath());
int[][] uvLoc = BitTwiddle.byteToUShort(uvBytes, 2, (int) fg.iVals[UV_BUFFER_OFFSET], (int) fg.iVals[UV_BUFFER_STRIDE]);
out.setCurrentTexture("" + c2++, 512, 512);
Tex tex = fg.tex;
File texFile = null;
if (tex != null && (texFile = new File(folder, tex.filename)).exists()) {
File mat = DTX1.toPNG(Files.readAllBytes(texFile.toPath()), outFolder, tex.width, tex.height);
out.setCurrentTexture(mat.getName(), tex.width, tex.height);
} else {
out.setCurrentTexture("missing_" + c2, 1, 1);
System.err.println("missing texture!" + c2);
}
for (int i = 2; i < fg.iVals[TRI_COUNT]; i++) {
// GL_TRIANGLES
int a = ind[i], b = ind[i - (i % 2 == 0 ? 2 : 1)], c = ind[i - (i % 2 == 0 ? 1 : 2)];
if (a != b && b != c && c != a && // google viewer magically hides some verts
isMagic8Visible(fg.magic8, vtLoc[a][3]) && isMagic8Visible(fg.magic8, vtLoc[b][3]) && isMagic8Visible(fg.magic8, vtLoc[c][3]) && // removes the tabs from the edges and centers of tiles (much easier before transform)
!isTab(vtLoc[a], vtLoc[b], vtLoc[c])) {
float[][] pos = new float[][] { locTrans(vtLoc[a], meshTransform), locTrans(vtLoc[b], meshTransform), locTrans(vtLoc[c], meshTransform) };
out.addFace(pos, new float[][] { uvMunge(uvLoc[a][0], uvLoc[a][1], tex, fg.fVals), uvMunge(uvLoc[b][0], uvLoc[b][1], tex, fg.fVals), uvMunge(uvLoc[c][0], uvLoc[c][1], tex, fg.fVals) }, findNormals(pos));
}
}
if (miniMesh != null) {
// out.writeMtlFile = false;
out.dump(new File(miniFrameFolder, "model.obj"));
}
}
}
if (miniMesh == null)
out.dump(new File(folder, "model.obj"));
else {
File f = new File(miniMesh, "index.xml");
f.getParentFile().mkdirs();
new XStream().toXML(miniTransform, new FileOutputStream(f));
}
}
use of org.twak.utils.collections.CountThings in project chordatlas by twak.
the class Regularizer method findOuters.
private void findOuters(MiniFacade mf) {
mf.outers.clear();
for (Feature f : Feature.values()) {
if (f != Feature.WINDOW)
continue;
Set<FRect> togo = new LinkedHashSet(mf.rects.get(f));
while (!togo.isEmpty()) {
AOuter outer = new AOuter(f);
FRect first = findBest(togo);
Set<FRect> neighbours = new TreeSet<>(FRect.comparatorArea(false));
neighbours.add(first);
while (!neighbours.isEmpty()) {
FRect n = neighbours.iterator().next();
if (!togo.contains(n)) {
neighbours.remove(n);
continue;
}
if (outer.easyAdd(n)) {
neighbours.remove(n);
add(togo, neighbours, n);
} else {
n = findBest(neighbours);
neighbours.remove(n);
if (outer.extend(n))
add(togo, neighbours, n);
}
}
if (outer.building.findPositions().values().size() >= 2) {
outer.done();
mf.outers.add(outer);
// re-ground the grid coordinate system
CountThings<Integer> xes = new CountThings<>(), yes = new CountThings<>();
for (int x = 0; x < outer.elements.length; x++) for (int y = 0; y < outer.elements[0].length; y++) if (outer.elements[x][y] != null) {
xes.count(x);
yes.count(y);
}
double halfAvgX = 0.5 * xes.getSize() / xes.counts.cache.keySet().size(), halfAvgY = 0.5 * yes.getSize() / yes.counts.cache.keySet().size();
List<Integer> rows = new ArrayList(xes.counts.cache.keySet());
Collections.sort(rows);
int xMin = rows.stream().filter(row -> xes.total(row) > halfAvgX).findFirst().get();
Collections.reverse(rows);
int xMax = rows.stream().filter(row -> xes.total(row) > halfAvgX).findFirst().get();
List<Integer> cols = new ArrayList(yes.counts.cache.keySet());
int yMin = cols.stream().filter(col -> yes.total(col) > halfAvgY).findFirst().get();
Collections.reverse(cols);
int yMax = cols.stream().filter(col -> yes.total(col) > halfAvgY).findFirst().get();
for (int x = 0; x < outer.elements.length; x++) for (int y = 0; y < outer.elements[0].length; y++) {
FRect w = outer.elements[x][y];
if (w == null)
continue;
w.gridCoords = new int[] { w.xi - xMin, xMax - w.xi, w.yi - yMin, yMax - w.yi };
if (mf.softLeft)
w.gridCoords[0] = -Integer.MAX_VALUE;
if (mf.softRight)
w.gridCoords[1] = -Integer.MAX_VALUE;
}
}
}
}
}
Aggregations