Search in sources :

Example 1 with AnyToXYTransform

use of org.poly2tri.transform.coordinate.AnyToXYTransform in project energy3d by concord-consortium.

the class MeshLib method applyHoles.

public static void applyHoles(final Node root, final List<Window> windows) {
    final Map<Window, List<ReadOnlyVector3>> holes = new HashMap<Window, List<ReadOnlyVector3>>();
    for (final Window window : windows) {
        final ArrayList<ReadOnlyVector3> hole = new ArrayList<ReadOnlyVector3>();
        hole.add(window.getAbsPoint(0).multiplyLocal(1, 1, 0));
        hole.add(window.getAbsPoint(2).multiplyLocal(1, 1, 0));
        hole.add(window.getAbsPoint(3).multiplyLocal(1, 1, 0));
        hole.add(window.getAbsPoint(1).multiplyLocal(1, 1, 0));
        holes.put(window, hole);
    }
    for (int roofIndex = 0; roofIndex < root.getChildren().size(); roofIndex++) {
        final Spatial roofPart = root.getChildren().get(roofIndex);
        if (roofPart.getSceneHints().getCullHint() != CullHint.Always) {
            final ReadOnlyVector3 normal = (ReadOnlyVector3) roofPart.getUserData();
            final AnyToXYTransform toXY = new AnyToXYTransform(normal.getX(), normal.getY(), normal.getZ());
            final XYToAnyTransform fromXY = new XYToAnyTransform(normal.getX(), normal.getY(), normal.getZ());
            final Mesh mesh = (Mesh) ((Node) roofPart).getChild(0);
            final ArrayList<ReadOnlyVector3> points3D = computeOutline(mesh.getMeshData().getVertexBuffer());
            final List<PolygonPoint> points2D = new ArrayList<PolygonPoint>();
            final ReadOnlyVector3 firstPoint = points3D.get(0);
            final double scale = Scene.getInstance().getTextureMode() == TextureMode.Simple ? 0.5 : 0.1;
            final TPoint o;
            final TPoint u;
            final TPoint v;
            if (normal.dot(Vector3.UNIT_Z) == 1) {
                o = new TPoint(firstPoint.getX(), firstPoint.getY(), firstPoint.getZ());
                u = new TPoint(1 / scale, 0, 0);
                v = new TPoint(0, 1 / scale, 0);
            } else {
                final ReadOnlyVector3 u3 = Vector3.UNIT_Z.cross(normal, null).normalizeLocal();
                final ReadOnlyVector3 ou3 = u3.divide(scale, null).add(firstPoint, null);
                final ReadOnlyVector3 ov3 = normal.cross(u3, null).divideLocal(scale).addLocal(firstPoint);
                o = new TPoint(firstPoint.getX(), firstPoint.getY(), firstPoint.getZ());
                u = new TPoint(ou3.getX(), ou3.getY(), ou3.getZ());
                v = new TPoint(ov3.getX(), ov3.getY(), ov3.getZ());
                toXY.transform(o);
                toXY.transform(u);
                toXY.transform(v);
                u.set(u.getX() - o.getX(), u.getY() - o.getY(), 0);
                v.set(v.getX() - o.getX(), v.getY() - o.getY(), 0);
            }
            final Vector2 o2 = new Vector2(firstPoint.getX(), firstPoint.getY());
            final Vector2 ou2 = o2.add(new Vector2(u.getX(), u.getY()), null);
            final Vector2 ov2 = o2.add(new Vector2(v.getX(), v.getY()), null);
            double minLineScaleU = Double.MAX_VALUE;
            double minLineScaleV = Double.MAX_VALUE;
            for (final ReadOnlyVector3 p : points3D) {
                final PolygonPoint polygonPoint = new PolygonPoint(p.getX(), p.getY(), p.getZ());
                toXY.transform(polygonPoint);
                points2D.add(polygonPoint);
                final Vector2 p2 = new Vector2(polygonPoint.getX(), polygonPoint.getY());
                final double lineScaleU = Util.projectPointOnLineScale(p2, o2, ou2);
                final double lineScaleV = Util.projectPointOnLineScale(p2, o2, ov2);
                if (lineScaleU < minLineScaleU) {
                    minLineScaleU = lineScaleU;
                }
                if (lineScaleV < minLineScaleV) {
                    minLineScaleV = lineScaleV;
                }
            }
            o2.addLocal(new Vector2(u.getX(), u.getY()).multiplyLocal(minLineScaleU));
            o2.addLocal(new Vector2(v.getX(), v.getY()).multiplyLocal(minLineScaleV));
            final PolygonWithHoles polygon = new PolygonWithHoles(points2D);
            o.set(o2.getX(), o2.getY(), 0);
            roofPart.updateWorldBound(true);
            for (final Window window : windows) {
                if (holes.get(window) == null) {
                    continue;
                }
                final List<PolygonPoint> holePolygon = new ArrayList<PolygonPoint>();
                boolean outside = false;
                for (final ReadOnlyVector3 holePoint : holes.get(window)) {
                    final PickResults pickResults = new PrimitivePickResults();
                    PickingUtil.findPick(((Node) roofPart).getChild(0), new Ray3(holePoint, Vector3.UNIT_Z), pickResults, false);
                    if (pickResults.getNumber() > 0) {
                        final ReadOnlyVector3 intersectionPoint = pickResults.getPickData(0).getIntersectionRecord().getIntersectionPoint(0);
                        final PolygonPoint polygonPoint = new PolygonPoint(intersectionPoint.getX(), intersectionPoint.getY(), intersectionPoint.getZ());
                        toXY.transform(polygonPoint);
                        holePolygon.add(polygonPoint);
                    } else {
                        outside = true;
                        break;
                    }
                }
                if (!outside) {
                    polygon.addHole(new PolygonWithHoles(holePolygon));
                    holes.remove(window);
                    window.setRoofIndex(roofIndex);
                }
            }
            final Mesh meshWithHoles = (Mesh) ((Node) roofPart).getChild(6);
            try {
                fillMeshWithPolygon(meshWithHoles, polygon, fromXY, true, o, v, u, false);
            } catch (final RuntimeException e) {
                e.printStackTrace();
                final Mesh meshWithoutHoles = (Mesh) ((Node) roofPart).getChild(0);
                meshWithHoles.setMeshData(meshWithoutHoles.getMeshData());
            }
        }
    }
}
Also used : Window(org.concord.energy3d.model.Window) AnyToXYTransform(org.poly2tri.transform.coordinate.AnyToXYTransform) HashMap(java.util.HashMap) Node(com.ardor3d.scenegraph.Node) ArrayList(java.util.ArrayList) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) Mesh(com.ardor3d.scenegraph.Mesh) CullHint(com.ardor3d.scenegraph.hint.CullHint) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) TPoint(org.poly2tri.triangulation.point.TPoint) Ray3(com.ardor3d.math.Ray3) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) XYToAnyTransform(org.poly2tri.transform.coordinate.XYToAnyTransform) Spatial(com.ardor3d.scenegraph.Spatial) ReadOnlyVector2(com.ardor3d.math.type.ReadOnlyVector2) Vector2(com.ardor3d.math.Vector2) ArrayList(java.util.ArrayList) List(java.util.List) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) PickResults(com.ardor3d.intersection.PickResults)

Example 2 with AnyToXYTransform

use of org.poly2tri.transform.coordinate.AnyToXYTransform in project energy3d by concord-consortium.

the class SolarRadiation method initMeshTextureData.

private MeshDataStore initMeshTextureData(final Mesh drawMesh, final Mesh collisionMesh, final ReadOnlyVector3 normal, final boolean updateTexture) {
    final MeshDataStore data = new MeshDataStore();
    if (normal != null) {
        final AnyToXYTransform toXY = new AnyToXYTransform(normal.getX(), normal.getY(), normal.getZ());
        final XYToAnyTransform fromXY = new XYToAnyTransform(normal.getX(), normal.getY(), normal.getZ());
        final FloatBuffer vertexBuffer = collisionMesh.getMeshData().getVertexBuffer();
        vertexBuffer.rewind();
        double minX, minY, maxX, maxY;
        minX = minY = Double.POSITIVE_INFINITY;
        maxX = maxY = Double.NEGATIVE_INFINITY;
        double z = Double.NaN;
        final List<ReadOnlyVector2> points = new ArrayList<ReadOnlyVector2>(vertexBuffer.limit() / 3);
        while (vertexBuffer.hasRemaining()) {
            final Vector3 pWorld = drawMesh.localToWorld(new Vector3(vertexBuffer.get(), vertexBuffer.get(), vertexBuffer.get()), null);
            final Point p = new TPoint(pWorld.getX(), pWorld.getY(), pWorld.getZ());
            toXY.transform(p);
            if (p.getX() < minX) {
                minX = p.getX();
            }
            if (p.getX() > maxX) {
                maxX = p.getX();
            }
            if (p.getY() < minY) {
                minY = p.getY();
            }
            if (p.getY() > maxY) {
                maxY = p.getY();
            }
            if (Double.isNaN(z)) {
                z = p.getZ();
            }
            points.add(new Vector2(p.getX(), p.getY()));
        }
        final Point tmp = new TPoint(minX, minY, z);
        fromXY.transform(tmp);
        data.p0 = new Vector3(tmp.getX(), tmp.getY(), tmp.getZ());
        tmp.set(minX, maxY, z);
        fromXY.transform(tmp);
        data.p1 = new Vector3(tmp.getX(), tmp.getY(), tmp.getZ());
        tmp.set(maxX, minY, z);
        fromXY.transform(tmp);
        data.p2 = new Vector3(tmp.getX(), tmp.getY(), tmp.getZ());
        final double solarStep = Scene.getInstance().getSolarStep();
        data.rows = Math.max(1, (int) Math.ceil(data.p1.subtract(data.p0, null).length() / solarStep));
        data.cols = Math.max(1, (int) Math.ceil(data.p2.subtract(data.p0, null).length() / solarStep));
        data.dailySolarIntensity = new double[Util.roundToPowerOfTwo(data.rows)][Util.roundToPowerOfTwo(data.cols)];
        final ReadOnlyVector2 originXY = new Vector2(minX, minY);
        final ReadOnlyVector2 uXY = new Vector2(maxX - minX, 0).normalizeLocal();
        final ReadOnlyVector2 vXY = new Vector2(0, maxY - minY).normalizeLocal();
        final int nrow = data.dailySolarIntensity.length;
        final int ncol = data.dailySolarIntensity[0].length;
        for (int row = 0; row < nrow; row++) {
            for (int col = 0; col < ncol; col++) {
                if (row >= data.rows || col >= data.cols) {
                    // overshot cells
                    data.dailySolarIntensity[row][col] = -1;
                } else {
                    final ReadOnlyVector2 p = originXY.add(uXY.multiply(col * solarStep, null), null).add(vXY.multiply(row * solarStep, null), null);
                    boolean isInside = false;
                    final int numberOfPoints = points.size();
                    if (numberOfPoints >= 3) {
                        // FIXME: sometimes we can end up with less than three points
                        for (int i = 0; i < numberOfPoints; i += 3) {
                            if (i + 2 < points.size()) {
                                if (Util.isPointInsideTriangle(p, points.get(i), points.get(i + 1), points.get(i + 2))) {
                                    isInside = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (!isInside && col > 0 && row > 0) {
                        // must at least include one column or row
                        data.dailySolarIntensity[row][col] = -1;
                    }
                }
            }
        }
        data.u = data.p2.subtract(data.p0, null).normalizeLocal();
        data.v = data.p1.subtract(data.p0, null).normalizeLocal();
        onMesh.put(drawMesh, data);
        if (updateTexture) {
            updateTextureCoords(drawMesh);
        }
    }
    return data;
}
Also used : AnyToXYTransform(org.poly2tri.transform.coordinate.AnyToXYTransform) ArrayList(java.util.ArrayList) FloatBuffer(java.nio.FloatBuffer) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) TPoint(org.poly2tri.triangulation.point.TPoint) CullHint(com.ardor3d.scenegraph.hint.CullHint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) ReadOnlyVector2(com.ardor3d.math.type.ReadOnlyVector2) XYToAnyTransform(org.poly2tri.transform.coordinate.XYToAnyTransform) ReadOnlyVector2(com.ardor3d.math.type.ReadOnlyVector2) Vector2(com.ardor3d.math.Vector2)

Example 3 with AnyToXYTransform

use of org.poly2tri.transform.coordinate.AnyToXYTransform in project energy3d by concord-consortium.

the class Wall method computeNormalAndXYTransform.

private void computeNormalAndXYTransform() {
    final Vector3 p02 = getAbsPoint(2).subtract(getAbsPoint(0), null).normalizeLocal();
    final Vector3 p01 = getAbsPoint(1).subtract(getAbsPoint(0), null).normalizeLocal();
    normal = p02.crossLocal(p01).normalizeLocal();
    toXY = new AnyToXYTransform(normal.getX(), normal.getY(), normal.getZ());
    fromXY = new XYToAnyTransform(normal.getX(), normal.getY(), normal.getZ());
}
Also used : AnyToXYTransform(org.poly2tri.transform.coordinate.AnyToXYTransform) XYToAnyTransform(org.poly2tri.transform.coordinate.XYToAnyTransform) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3)

Aggregations

ReadOnlyVector3 (com.ardor3d.math.type.ReadOnlyVector3)3 AnyToXYTransform (org.poly2tri.transform.coordinate.AnyToXYTransform)3 XYToAnyTransform (org.poly2tri.transform.coordinate.XYToAnyTransform)3 Vector2 (com.ardor3d.math.Vector2)2 Vector3 (com.ardor3d.math.Vector3)2 ReadOnlyVector2 (com.ardor3d.math.type.ReadOnlyVector2)2 CullHint (com.ardor3d.scenegraph.hint.CullHint)2 ArrayList (java.util.ArrayList)2 Point (org.poly2tri.geometry.primitives.Point)2 TPoint (org.poly2tri.triangulation.point.TPoint)2 PickResults (com.ardor3d.intersection.PickResults)1 PrimitivePickResults (com.ardor3d.intersection.PrimitivePickResults)1 Ray3 (com.ardor3d.math.Ray3)1 Mesh (com.ardor3d.scenegraph.Mesh)1 Node (com.ardor3d.scenegraph.Node)1 Spatial (com.ardor3d.scenegraph.Spatial)1 FloatBuffer (java.nio.FloatBuffer)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Window (org.concord.energy3d.model.Window)1