use of org.twak.utils.geom.LinearForm3D 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.LinearForm3D in project chordatlas by twak.
the class Tube method tube.
public static void tube(MeshBuilder out, Collection<LinearForm3D> before, Collection<LinearForm3D> after, Line3d line, LinearForm3D left, LinearForm3D right, CrossGen gen) {
if (angle(before, line) < 0.1 || angle(after, line) < 0.1)
// too pointy to touch
return;
Point3d middle = line.fromPPram(0.5);
Vector3d along = line.dir();
along.normalize();
Vector3d nAlong = new Vector3d(along);
nAlong.negate();
Vector3d o1 = left.normal(), u1 = new Vector3d();
u1.cross(along, o1);
Frame frame = Mathz.buildFrame(o1, u1, along, middle);
Vector3d u2 = right.normal();
u2.cross(u2, along);
// u2.add( middle );
Vector2d leftDir = Mathz.toXY(frame, u1);
Vector2d rightDir = Mathz.toXY(frame, u2);
List<Point3d> profilePts = gen.gen(leftDir, rightDir).stream().map(p -> Mathz.fromXY(frame, p)).collect(Collectors.toList());
List<LinearForm3D> dummy = new ArrayList<>();
for (Pair<Point3d, Point3d> pair : new ConsecutivePairs<Point3d>(profilePts, true)) {
Point3d f1 = clip(pair.first(), along, after, dummy), f2 = clip(pair.second(), along, after, dummy), b1 = clip(pair.first(), nAlong, before, dummy), b2 = clip(pair.second(), nAlong, before, dummy);
out.add(f2, f1, b1, b2);
}
// cap( out, after , along, profilePts, true );
// cap( out, before, nAlong, profilePts, false );
}
use of org.twak.utils.geom.LinearForm3D in project chordatlas by twak.
the class Tube method clip.
private static Point3d clip(Point3d pt, Vector3d dir, Collection<LinearForm3D> after, List<LinearForm3D> hit) {
Point3d out = pt;
double bestScore = Double.MAX_VALUE;
Line3d line = Line3d.fromRay(pt, dir);
for (LinearForm3D l : after) {
if (l == null)
continue;
Point3d sec = l.collide(pt, dir);
if (sec == null)
continue;
double score = line.findPPram(sec);
if (score < bestScore) {
out = sec;
bestScore = score;
}
}
for (LinearForm3D l : after) {
if (l == null)
continue;
Point3d sec = l.collide(pt, dir);
if (sec != null) {
double score = line.findPPram(sec);
if (Math.abs(score - bestScore) < 0.00001)
hit.add(l);
}
}
return out;
}
use of org.twak.utils.geom.LinearForm3D in project chordatlas by twak.
the class Tube method cap.
private static void cap(MeshBuilder out, Collection<LinearForm3D> after, Vector3d along, List<Point3d> profilePts, boolean reverse) {
MultiMap<LinearForm3D, Point3d> faces = new MultiMap<>();
for (Point3d p : profilePts) {
List<LinearForm3D> hit = new ArrayList<>();
Point3d c = clip(p, along, after, hit);
for (LinearForm3D h : hit) faces.put(h, c);
}
for (Map.Entry<LinearForm3D, List<Point3d>> e : faces.map.entrySet()) out.add(new Loop<Point3d>(e.getValue()).singleton(), null, reverse);
}
use of org.twak.utils.geom.LinearForm3D in project chordatlas by twak.
the class GreebleEdge method roowWallGreeble.
public static void roowWallGreeble(Output output, MeshBuilder roof, MeshBuilder wall) {
MultiMap<Point3d, SharedEdge> boundary = new MultiMap<>();
Set<SharedEdge> roofWallBoundary = new HashSet<>();
for (Face f1 : output.faces.values()) for (Loop<SharedEdge> sl : f1.edges) for (Loopable<SharedEdge> se : sl.loopableIterator()) {
Face f2 = se.get().getOther(f1);
if (isWall(f1) ^ isWall(f2)) {
boundary.put(se.get().getStart(f1), se.get());
roofWallBoundary.add(se.get());
}
}
for (SharedEdge se : roofWallBoundary) {
if (se.start.z < 1 || se.end.z < 1)
// something strange here...
continue;
Face f1 = se.left, f2 = se.right;
if (f1 == null || f2 == null)
continue;
EdgePoint bs = findAdjacent(se.start, se.end, boundary), be = findAdjacent(se.end, se.start, boundary);
if (bs != null && be != null) {
LinearForm3D cutS, cutE;
if (isOverhang(bs.se))
// between two angles
cutS = cut(bs.pt, se.start, se.end);
else
// flat at end
cutS = new LinearForm3D(LinearForm3D.linePerp(toXZ(se.end), toXZ(se.start)));
if (isOverhang(be.se))
cutE = cut(se.start, se.end, be.pt);
else
// flat at end
cutE = new LinearForm3D(LinearForm3D.linePerp(toXZ(se.start), toXZ(se.end)));
LinearForm3D right = new LinearForm3D(toXZ(f1.edge.getPlaneNormal()), toXZ(f1.edge.start)), left = new LinearForm3D(toXZ(f2.edge.getPlaneNormal()), toXZ(f2.edge.start));
Tube.tube(roof, Collections.singleton(cutS), Collections.singleton(cutE), new Line3d(toXZ(se.start), toXZ(se.end)), left, right, isOverhang(se) ? new OverhangCross() : new LipCross());
}
}
}
Aggregations