Search in sources :

Example 1 with CountThings

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));
    }
}
Also used : HashMap(java.util.HashMap) Vector4d(javax.vecmath.Vector4d) ObjDump(org.twak.utils.geom.ObjDump) CountThings(org.twak.utils.collections.CountThings) HashSet(java.util.HashSet) XStream(com.thoughtworks.xstream.XStream) Matrix4d(javax.vecmath.Matrix4d) FileOutputStream(java.io.FileOutputStream) File(java.io.File)

Example 2 with CountThings

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;
                }
            }
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ArrayList(java.util.ArrayList) Feature(org.twak.viewTrace.facades.MiniFacade.Feature) TreeSet(java.util.TreeSet) CountThings(org.twak.utils.collections.CountThings)

Aggregations

CountThings (org.twak.utils.collections.CountThings)2 XStream (com.thoughtworks.xstream.XStream)1 File (java.io.File)1 FileOutputStream (java.io.FileOutputStream)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedHashSet (java.util.LinkedHashSet)1 TreeSet (java.util.TreeSet)1 Matrix4d (javax.vecmath.Matrix4d)1 Vector4d (javax.vecmath.Vector4d)1 ObjDump (org.twak.utils.geom.ObjDump)1 Feature (org.twak.viewTrace.facades.MiniFacade.Feature)1