use of javax.vecmath.Matrix4d in project chordatlas by twak.
the class GreebleCGA method cga.
protected double cga(Loop<Point2d> rect, Matrix4d to3d, WallTag wallTag, MeshBuilder normalWall, MeshBuilder ground, Cache<float[], MeshBuilder> mbs, List<DRectangle> occlusions) {
double[] bounds = Loopz.minMax2d(rect);
GreebleGrid gg = new GreebleGrid(tweed, new MMeshBuilderCache());
DRectangle all = new DRectangle(bounds[0], bounds[2], bounds[1] - bounds[0], bounds[3] - bounds[2]);
// for (DRectangle d : occlusions)
// mbs.get( new float[] {1,1,0,1} ).add( d, to3d );
float[] windowColor = new float[] { 0.8f, .8f, 0.8f, 1 }, glassColor = new float[] { 0.3f, 0.3f, 1, 1 }, mouldingColor = new float[] { 0.7f, .7f, 0.7f, 1 };
double groundFloorHeight = 0;
List<DRectangle> floors = all.splitY(r -> splitFloors(r, 3, 2.5, 2));
for (int f = 0; f < floors.size(); f++) {
boolean isGround = f == 0 && wallTag.isGroundFloor;
DRectangle floor = floors.get(f);
MeshBuilder wall = isGround ? ground : normalWall;
List<DRectangle> edges = floor.splitX(r -> split3(r, 1, 1));
if (isGround)
groundFloorHeight = floor.height;
if (edges.size() != 3) {
wall.add(floor, to3d);
} else {
wall.add(edges.get(0), to3d);
wall.add(edges.get(edges.size() - 1), to3d);
DRectangle cen = edges.get(1);
if (cen.height < 1.8)
wall.add(cen, to3d);
else {
if (f == 0 && wallTag.isGroundFloor) {
List<DRectangle> groundPanel = cen.splitX(r -> split1(r, 0.9));
if (groundPanel.get(0).width < 0.7)
wall.add(groundPanel.get(0), to3d);
else if (wallTag.makeDoor) {
List<DRectangle> doorHeight = groundPanel.get(0).splitY(r -> split1(r, 2.2));
if (visible(doorHeight.get(0), occlusions))
greebleGrid.createDoor(doorHeight.get(0), to3d, wall, mbs.get(windowColor), wallTag.doorDepth);
else
wall.add(doorHeight.get(0), to3d);
if (doorHeight.size() > 1)
wall.add(doorHeight.get(1), to3d);
if (groundPanel.size() > 1) {
List<DRectangle> gWindowPanelH = groundPanel.get(1).splitX(r -> split3(r, 0.5, 0.0));
if (gWindowPanelH.size() > 2) {
wall.add(gWindowPanelH.get(0), to3d);
wall.add(gWindowPanelH.get(2), to3d);
List<DRectangle> gWindowPanelV = gWindowPanelH.get(1).splitY(r -> split3(r, 0.5, 0.5));
if (gWindowPanelV.size() > 2) {
wall.add(gWindowPanelV.get(0), to3d);
wall.add(gWindowPanelV.get(2), to3d);
if (visible(gWindowPanelV.get(1), occlusions))
greebleGrid.createWindow(gWindowPanelV.get(1), to3d, wall, mbs.get(windowColor), mbs.get(glassColor), wallTag.windowDepth, -1, -1, -1, 0.6, 0.9);
else
wall.add(gWindowPanelV.get(1), to3d);
} else
for (DRectangle d : gWindowPanelV) wall.add(d, to3d);
} else
for (DRectangle d : gWindowPanelH) wall.add(d, to3d);
}
} else
windowStrip(to3d, wallTag, mbs.get(windowColor), mbs.get(glassColor), wall, cen, false, occlusions, greebleGrid);
} else {
windowStrip(to3d, wallTag, mbs.get(windowColor), mbs.get(glassColor), wall, cen, f > 0 && f < floors.size() - 1 && wallTag.makeBalcony, occlusions, greebleGrid);
if (f == 1 && wallTag.isGroundFloor)
greebleGrid.moulding(to3d, new DRectangle(floor.x, floor.y, floor.width, 0.5), mbs.get(mouldingColor));
}
}
}
}
return groundFloorHeight;
}
use of javax.vecmath.Matrix4d in project chordatlas by twak.
the class AlignTool method doAlign.
private void doAlign() {
if (alignMarkers[0] == null || alignMarkers[1] == null || otherMarkers[0] == null || otherMarkers[1] == null) {
JOptionPane.showMessageDialog(null, "click meshes to create align markers");
return;
}
Matrix4d toOrigin = buildFrame(alignMarkers);
toOrigin.invert();
Matrix4d o = buildFrame(otherMarkers);
toOrigin.mul(o, toOrigin);
toOrigin.m13 += vOffset;
Transform t = new Transform();
t.fromTransformMatrix(Jme3z.toJme(toOrigin));
toAlign.moveTo(t);
// System.out.println ( "bounds "+ toAlign.gNode.getWorldBound() );
}
use of javax.vecmath.Matrix4d in project chordatlas by twak.
the class MiniTransform method convertToMini.
public static void convertToMini(Iterable<File> bigObj, File outfile, Matrix4d transform) {
outfile.mkdirs();
// .iterator().next() );
ObjDump src = new ObjDump(bigObj);
src.centerVerts();
src.transform(transform);
long count = src.material2Face.entrySet().stream().mapToInt(x -> x.getValue().size()).sum();
double[] bounds = src.orderVert.stream().collect(new InaxPoint3dCollector());
long targetCount = 5000;
double volume = (bounds[1] - bounds[0]) * (bounds[3] - bounds[2]) * (bounds[5] - bounds[4]);
double edgeLength = Math.pow(volume / (count / targetCount), 0.3333);
int xc = (int) Math.ceil((bounds[1] - bounds[0]) / edgeLength), yc = (int) Math.ceil((bounds[3] - bounds[2]) / edgeLength), zc = (int) Math.ceil((bounds[5] - bounds[4]) / edgeLength);
Set<Face>[][][] faces = new Set[xc][yc][zc];
for (Entry<Material, List<Face>> e : src.material2Face.entrySet()) for (Face f : e.getValue()) {
Tuple3d vt = src.orderVert.get(f.vtIndexes.get(0));
int ix = (int) ((vt.x - bounds[0]) / edgeLength);
int iy = (int) ((vt.y - bounds[2]) / edgeLength);
int iz = (int) ((vt.z - bounds[4]) / edgeLength);
if (faces[ix][iy][iz] == null)
faces[ix][iy][iz] = new HashSet();
faces[ix][iy][iz].add(f);
}
int dir = 0;
MiniTransform mt = new MiniTransform();
for (int x = 0; x < xc; x++) for (int y = 0; y < yc; y++) for (int z = 0; z < zc; z++) {
Set<Face> miniF = faces[x][y][z];
if (miniF == null)
continue;
Matrix4d trans = new Matrix4d();
trans.setIdentity();
trans.setScale(edgeLength / 255);
trans.setTranslation(new Vector3d(x * edgeLength + bounds[0], y * edgeLength + bounds[2], z * edgeLength + bounds[4]));
Matrix4d pack = new Matrix4d(trans);
pack.invert();
ObjDump mini = new ObjDump();
miniF.stream().forEach(f -> mini.addFaceFrom(f, src));
mini.transform(pack);
mini.dump(new File(new File(outfile, "" + dir), OBJ));
mt.index.put(dir, trans);
dir++;
}
try {
new XStream().toXML(mt, new FileWriter(new File(outfile, INDEX)));
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("wrote " + count + " faces to " + dir + " meshes");
}
use of javax.vecmath.Matrix4d in project chordatlas by twak.
the class ReadTrace method processLine.
private void processLine(String line) throws Throwable {
set(glDrawElementsRE, line, TRI_COUNT);
Matcher m = glVertexAttrib.matcher(line);
if (m.matches()) {
if (m.group(1).equals("BYTE")) {
iVals[VERTEX_BUFFER] = boundBuffer.get(ARRAY_BUFFER);
iVals[VERTEX_BUFFER_OFFSET] = m.group(3).equals("NULL") ? 0 : Integer.parseUnsignedInt(m.group(3).substring(2), 16);
iVals[VERTEX_BUFFER_STRIDE] = Integer.parseInt(m.group(2));
}
if (m.group(1).equals("SHORT")) {
iVals[UV_BUFFER] = boundBuffer.get(ARRAY_BUFFER);
iVals[UV_BUFFER_OFFSET] = m.group(3).equals("NULL") ? 0 : Integer.parseInt(m.group(3).substring(2), 16);
iVals[UV_BUFFER_STRIDE] = Integer.parseInt(m.group(2));
}
}
m = magic8Pattern.matcher(line);
if (m.matches())
for (int i = 1; i < 9; i++) magic8[i - 1] = Double.parseDouble(m.group(i));
m = viewMatrixPattern.matcher(line);
if (m.matches()) {
for (int xi = 0; xi < 4; xi++) for (int yi = 0; yi < 4; yi++) viewMatrix.setElement(xi, yi, Double.parseDouble(m.group(xi + yi * 4 + 1)));
if (matrixForAntiWibble == null) {
matrixForAntiWibble = new Matrix4d(viewMatrix);
try {
matrixForAntiWibble.invert();
} catch (Throwable th) {
matrixForAntiWibble = null;
}
}
if (matrixForAntiWibble != null)
viewMatrix.mul(matrixForAntiWibble, viewMatrix);
}
m = uvParams.matcher(line);
if (m.matches())
for (int i = 0; i < 4; i++) fVals[UV_PARAM_X + i] = Float.parseFloat(m.group(1 + i));
}
use of javax.vecmath.Matrix4d 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));
}
}
Aggregations