use of org.twak.utils.geom.ObjDump.Face in project chordatlas by twak.
the class MiniGen method clip.
public void clip(Loop<Point3d> in, File objLocation) {
ObjDump obj = new ObjDump();
double[] bounds = Loopz.minMaxXZ(in);
List<LinearForm3D> halfPlanes = new ArrayList();
File writeFolder = objLocation.getParentFile();
for (Pair<Point3d, Point3d> p : in.pairs()) {
Vector3d norm = new Vector3d(p.second());
norm.sub(p.first());
norm = new Vector3d(-norm.z, 0, norm.x);
norm.normalize();
halfPlanes.add(new LinearForm3D(norm, p.first()));
}
Map<File, File> copied = new HashMap<>();
int nameCount = 0;
double minY = Double.MAX_VALUE, maxY = -Double.MAX_VALUE;
for (Map.Entry<Integer, Matrix4d> e : trans.index.entrySet()) {
if (!inBounds(e.getValue(), Collections.singletonList(bounds)))
continue;
else {
Matrix4d m = new Matrix4d();
m.mul(Jme3z.fromMatrix(trans.offset), e.getValue());
File readFolder = new File(Tweed.toWorkspace(root), e.getKey() + "");
ObjDump or = new ObjDump(new File(readFolder, "model.obj"));
or.computeMissingNormals();
for (ObjDump.Material mat : or.material2Face.keySet()) {
f: for (Face f : or.material2Face.get(mat)) {
for (int j = 0; j < f.vtIndexes.size(); j++) {
Point3d pt = new Point3d(or.orderVert.get(f.vtIndexes.get(j)));
m.transform(pt);
if (pt.x > bounds[0] && pt.x < bounds[1] && pt.z > bounds[2] && pt.z < bounds[3])
if (inside(pt, halfPlanes)) {
if (IMPORT_TEXTURES && !((obj.currentMaterial != null && obj.currentMaterial.equals(mat)) || (obj.currentMaterial == null && mat == null))) {
File source = new File(readFolder, mat.filename);
ObjDump.Material newMat;
if (copied.containsKey(source)) {
newMat = new ObjDump.Material(mat);
newMat.filename = copied.get(source).getName();
} else {
newMat = makeUnique(mat, writeFolder);
File destFile = new File(writeFolder, newMat.filename);
copied.put(source, destFile);
try {
Files.copy(source.toPath(), new FileOutputStream(destFile));
} catch (IOException e1) {
e1.printStackTrace();
}
}
newMat.diffuse = new double[] { 0, 0, 0 };
newMat.ambient = new double[] { 1, 1, 1 };
newMat.specular = new double[] { 0, 0, 0 };
newMat.name = "mat_" + (nameCount++);
obj.setCurrentMaterial(newMat);
}
List<Point3d> fVerts = new ArrayList<>(3), fNorms = new ArrayList<>(3);
List<Point2d> fUVs = new ArrayList<>(2);
for (int i = 0; i < f.vtIndexes.size(); i++) {
Point3d vts = new Point3d(or.orderVert.get(f.vtIndexes.get(i)));
Point3d ns = new Point3d(or.orderNorm.get(f.normIndexes.get(i)));
ns.add(vts);
m.transform(vts);
m.transform(ns);
ns.sub(vts);
minY = Math.min(vts.y, minY);
maxY = Math.max(vts.y, maxY);
fVerts.add(vts);
fNorms.add(ns);
fUVs.add(new Point2d(or.orderUV.get(f.uvIndexes.get(i))));
}
obj.addFace(fVerts, fNorms, fUVs);
continue f;
}
}
}
}
}
}
for (Tuple3d t : obj.orderVert) t.y -= (maxY - minY) * 0.03 + minY;
obj.dump(objLocation);
}
use of org.twak.utils.geom.ObjDump.Face 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");
}
Aggregations