use of org.twak.siteplan.jme.MeshBuilder 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.siteplan.jme.MeshBuilder 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 org.twak.siteplan.jme.MeshBuilder in project chordatlas by twak.
the class WindowGen method calculate.
@Override
public void calculate() {
for (Spatial s : gNode.getChildren()) s.removeFromParent();
FeatureCache fg = tweed.features;
int i = 0;
if (fg != null) {
for (MegaFeatures mf : fg.getBlock(block.center).features) {
Vector3f along, up, in;
{
Vector2d mfl = mf.megafacade.dir();
mfl.normalize();
along = new Vector3f((float) mfl.x, 0, (float) mfl.y);
up = new Vector3f(0, 1, 0);
in = along.cross(up);
}
Vector3f mfStart = Jme3z.to(Pointz.to3(mf.megafacade.start));
for (ImageFeatures im : mf.features) {
MeshBuilder mb = new MeshBuilder();
float offset = (float) Math.random() * 5;
for (MiniFacade mini : im.miniFacades) {
for (DRectangle r : mini.rects.get(Feature.WINDOW)) {
Vector3f loc = new Vector3f(mfStart);
loc.addLocal(along.mult((float) r.x));
loc.addLocal(up.mult((float) r.y));
createWindow(mb, mb, new Window(loc.add(in.mult(offset + 0.4f)), along, up, r.width, r.height, 0.3, 0.4, 0.6));
}
if (!mini.rects.get(Feature.WINDOW).isEmpty()) {
Vector3f loc = new Vector3f(mfStart);
loc.addLocal(along.mult((float) mini.left)).addLocal(in.mult(offset));
mb.addCube(loc, up, along, in, (float) mini.height, (float) mini.width, 0.1f);
}
}
Geometry g = new Geometry(this.getClass().getSimpleName());
g.setMesh(mb.getMesh());
Material mat = new Material(tweed.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setColor("Diffuse", Jme3z.toJme(Rainbow.getColour(i)));
mat.setColor("Ambient", Jme3z.toJme(Rainbow.getColour(i)));
mat.setBoolean("UseMaterialColors", true);
g.setMaterial(mat);
i++;
gNode.attachChild(g);
}
}
}
super.calculate();
}
use of org.twak.siteplan.jme.MeshBuilder in project chordatlas by twak.
the class SkelFootprint method dbgShowProfiles.
private void dbgShowProfiles(HalfMesh2 mesh, List<Prof> globalProfs, Map<SuperEdge, double[]> profFit, String name) {
Node n = new Node();
Jme3z.removeAllChildren(n);
int colI = 0;
for (HalfFace f : mesh) {
ColorRGBA col = Jme3z.toJme(Rainbow.getColour(colI++));
colI = colI % 6;
Material mat = new Material(tweed.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
mat.setColor("Diffuse", col);
mat.setColor("Ambient", col);
mat.setBoolean("UseMaterialColors", true);
if (true) {
Loop<Point3d> loop = new Loop<>();
for (HalfEdge e : f) loop.append(new Point3d(e.start.x, 0, e.start.y));
MeshBuilder mb = new MeshBuilder();
mb.add(loop.singleton(), null, false);
Geometry g = new Geometry("floorplan", mb.getMesh());
g.setMaterial(mat);
n.attachChild(g);
}
for (HalfEdge e : f) {
SuperEdge se = (SuperEdge) e;
Prof bestProf = null;
if (globalProfs == null)
bestProf = se.prof;
else {
// if (se.profLine != null) {
//
// SuperLine sl = ((SuperLine)se.profLine);
// MegaFacade mf = (MegaFacade) sl.properties.get( MegaFacade.class.getName() );
//
// List<Prof> pfs = mf.getTween( se.start, se.end, 0.3 );
//
// if (!pfs.isEmpty())
// bestProf = Prof.parameterize( sl, pfs );
// else {
// bestProf = clean.get( 0 );
// double bestScore = Double.MAX_VALUE;
//
// for ( Prof c : clean ) {
//
// double score = 0;
// boolean good = false;
// for ( Prof r : mf.getTween( se.start, se.end, 0.3 ) ) {
// score += c.distance( r, true, false, true );
// good = true;
// }
// if ( good && score < bestScore ) {
// bestScore = score;
// bestProf = c;
// }
//
// }
// }
//
//
// }
// if (bestProf)
// ((SuperLine))
//
double[] fitV = profFit.get(se);
if (fitV == null)
continue;
double bestScore = Double.MAX_VALUE;
for (int ii = 0; ii < fitV.length; ii++) {
double d = fitV[ii];
if (d < bestScore) {
bestScore = d;
bestProf = globalProfs.get(ii);
}
}
//
// double bestScore = Double.MAX_VALUE;
//
// for ( int ii = 0; ii < fitV.length; ii++ ) {
// double d = fitV[ ii ];
// if ( d < bestScore ) {
// bestScore = d;
// bestProf = globalProfs.get( ii );
// }
// }
// if (false)
// se.prof = bestProf;
}
if (bestProf != null) {
Geometry g = new Geometry();
Point3d cen = Pointz.to3(se.line().fromPPram(0.5));
Prof goodOrientation = Prof.buildProfile(Pointz.to3(se.line()), cen);
for (Point2d p : bestProf) goodOrientation.add(p);
g.setMesh(goodOrientation.renderStrip(1.5, cen));
g.setMaterial(mat);
n.attachChild(g);
g.updateGeometricState();
g.updateModelBound();
}
}
}
skelGen.tweed.frame.addGen(new JmeGen(name, tweed, n), false);
}
use of org.twak.siteplan.jme.MeshBuilder in project chordatlas by twak.
the class GreebleGrid method createDormerWindow.
protected void createDormerWindow(QuadF l, MeshBuilder window, MeshBuilder glass, float sillDepth, float sillHeight, float corniceHeight, double panelWidth, double panelHeight) {
Vector3d along = new Vector3d(l.corners[3]);
along.sub(l.corners[0]);
along.normalize();
Vector3d up = new Vector3d(0, 1, 0);
Vector3d out = new Vector3d();
out.cross(along, up);
out.scale(1 / out.length());
Line3d lout;
{
Point3d away = new Point3d(l.corners[0]);
away.add(out);
lout = new Line3d(new Point3d(l.corners[0]), away);
}
Vector3d loc = new Vector3d(l.found[0]);
if (lout.findPPram(l.found[0]) < lout.findPPram(l.found[1])) {
// outwards going wall...
loc = new Vector3d(up);
loc.scale(-l.original.height);
loc.add(l.found[1]);
}
{
Vector3d avoidRoof = new Vector3d(out);
avoidRoof.scale(0.09);
;
loc.add(avoidRoof);
}
Point3d deepest = Arrays.stream(l.found).map(p -> new Pair<Point3d, Double>(p, lout.findPPram(p))).max((a, b) -> b.second().compareTo(a.second())).get().first();
double depth = lout.closestPointOn(deepest, false).distance(lout.closestPointOn(new Point3d(loc), false));
// MUtils.max(
// Math.abs (l.corners[0].distance( l.found[0] )),
// Math.abs (l.corners[1].distance( l.found[1] )),
// Math.abs (l.corners[2].distance( l.found[2] )),
// Math.abs (l.corners[3].distance( l.found[3] ))
// ) ;
WindowGen.createWindow(window, glass, new Window(Jme3z.to(loc), Jme3z.to(along), Jme3z.to(up), l.original.width, l.original.height, depth, panelWidth, panelHeight));
// Vector3f u = Jme3z.to(up), o = Jme3z.to( out );
// if (sillDepth > 0)
// window.addCube( Jme3z.to ( ptt[0] ).add( u.mult( -sillHeight + 0.01f ) ).add( o.mult( -sillDepth) ),
// Jme3z.to(out), Jme3z.to(along), Jme3z.to(up),
// (float)depth + sillDepth, (float)winPanel.width,(float) sillHeight );
//
// if (corniceHeight > 0)
// moulding( to3d, new DRectangle(winPanel.x, winPanel.getMaxY(), winPanel.width, corniceHeight), wall );
}
Aggregations