Search in sources :

Example 26 with Mesh

use of com.ardor3d.scenegraph.Mesh in project energy3d by concord-consortium.

the class SolarRadiation method computeOnMirror.

// unlike PV solar panels, no indirect (ambient or diffuse) radiation should be included in reflection calculation
private void computeOnMirror(final int minute, final ReadOnlyVector3 directionTowardSun, final Mirror mirror) {
    final int nx = Scene.getInstance().getMirrorNx();
    final int ny = Scene.getInstance().getMirrorNy();
    final Foundation target = mirror.getReceiver();
    if (target != null) {
        final Calendar calendar = Heliodon.getInstance().getCalendar();
        calendar.set(Calendar.HOUR_OF_DAY, (int) ((double) minute / (double) SolarRadiation.MINUTES_OF_DAY * 24.0));
        calendar.set(Calendar.MINUTE, minute % 60);
        mirror.draw();
    }
    // nx*ny*60: nx*ny is to get the unit cell area of the nx*ny grid; 60 is to convert the unit of timeStep from minute to kWh
    final double a = mirror.getMirrorWidth() * mirror.getMirrorHeight() * Scene.getInstance().getTimeStep() / (nx * ny * 60.0);
    final ReadOnlyVector3 normal = mirror.getNormal();
    if (normal == null) {
        throw new RuntimeException("Normal is null");
    }
    final Mesh mesh = mirror.getRadiationMesh();
    MeshDataStore data = onMesh.get(mesh);
    if (data == null) {
        data = initMeshTextureDataOnRectangle(mesh, nx, ny);
    }
    final ReadOnlyVector3 offset = directionTowardSun.multiply(1, null);
    final double dot = normal.dot(directionTowardSun);
    double directRadiation = 0;
    if (dot > 0) {
        directRadiation += calculateDirectRadiation(directionTowardSun, normal);
    }
    final FloatBuffer vertexBuffer = mesh.getMeshData().getVertexBuffer();
    // (0, 0)
    final Vector3 p0 = new Vector3(vertexBuffer.get(3), vertexBuffer.get(4), vertexBuffer.get(5));
    // (1, 0)
    final Vector3 p1 = new Vector3(vertexBuffer.get(6), vertexBuffer.get(7), vertexBuffer.get(8));
    // (0, 1)
    final Vector3 p2 = new Vector3(vertexBuffer.get(0), vertexBuffer.get(1), vertexBuffer.get(2));
    // final Vector3 q0 = drawMesh.localToWorld(p0, null);
    // final Vector3 q1 = drawMesh.localToWorld(p1, null);
    // final Vector3 q2 = drawMesh.localToWorld(p2, null);
    // System.out.println("***" + q0.distance(q1) * Scene.getInstance().getAnnotationScale() + "," + q0.distance(q2) * Scene.getInstance().getAnnotationScale());
    // this is the longer side (supposed to be y)
    final Vector3 u = p1.subtract(p0, null).normalizeLocal();
    // this is the shorter side (supposed to be x)
    final Vector3 v = p2.subtract(p0, null).normalizeLocal();
    // x and y must be swapped to have correct heat map texture, because nx represents rows and ny columns as we call initMeshTextureDataOnRectangle(mesh, nx, ny)
    final double xSpacing = p1.distance(p0) / nx;
    final double ySpacing = p2.distance(p0) / ny;
    final Vector3 receiver = target != null ? target.getSolarReceiverCenter() : null;
    List<Mesh> towerCollisionMeshes = null;
    if (target != null) {
        towerCollisionMeshes = new ArrayList<Mesh>();
        for (final HousePart child : target.getChildren()) {
            towerCollisionMeshes.add((Mesh) child.getRadiationCollisionSpatial());
        }
        final List<Roof> roofs = target.getRoofs();
        if (!roofs.isEmpty()) {
            for (final Roof r : roofs) {
                for (final Spatial roofPart : r.getRoofPartsRoot().getChildren()) {
                    towerCollisionMeshes.add((Mesh) ((Node) roofPart).getChild(6));
                }
            }
        }
    }
    final int iMinute = minute / Scene.getInstance().getTimeStep();
    final boolean reflectionMapOnly = Scene.getInstance().getOnlyReflectedEnergyInMirrorSolarMap();
    for (int x = 0; x < nx; x++) {
        for (int y = 0; y < ny; y++) {
            if (EnergyPanel.getInstance().isCancelled()) {
                throw new CancellationException();
            }
            final Vector3 u2 = u.multiply(xSpacing * (x + 0.5), null);
            final Vector3 v2 = v.multiply(ySpacing * (y + 0.5), null);
            final ReadOnlyVector3 p = mesh.getWorldTransform().applyForward(p0.add(v2, null).addLocal(u2)).addLocal(offset);
            final Ray3 pickRay = new Ray3(p, directionTowardSun);
            if (dot > 0) {
                final PickResults pickResults = new PrimitivePickResults();
                for (final Spatial spatial : collidables) {
                    if (spatial != mesh) {
                        PickingUtil.findPick(spatial, pickRay, pickResults, false);
                        if (pickResults.getNumber() != 0) {
                            break;
                        }
                    }
                }
                if (pickResults.getNumber() == 0) {
                    // for heat map generation
                    if (!reflectionMapOnly) {
                        data.dailySolarIntensity[x][y] += directRadiation;
                    }
                    if (receiver != null) {
                        // for concentrated energy calculation
                        final Vector3 toReceiver = receiver.subtract(p, null);
                        final Ray3 rayToReceiver = new Ray3(p, toReceiver.normalize(null));
                        final PickResults pickResultsToReceiver = new PrimitivePickResults();
                        for (final Spatial spatial : collidables) {
                            if (spatial != mesh) {
                                if (towerCollisionMeshes == null || (towerCollisionMeshes != null && !towerCollisionMeshes.contains(spatial))) {
                                    PickingUtil.findPick(spatial, rayToReceiver, pickResultsToReceiver, false);
                                    if (pickResultsToReceiver.getNumber() != 0) {
                                        break;
                                    }
                                }
                            }
                        }
                        if (pickResultsToReceiver.getNumber() == 0) {
                            final double r = directRadiation * Atmosphere.getTransmittance(toReceiver.length() * Scene.getInstance().getAnnotationScale() * 0.001, false);
                            mirror.getSolarPotential()[iMinute] += r * a;
                            if (reflectionMapOnly) {
                                data.dailySolarIntensity[x][y] += r;
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : Calendar(java.util.Calendar) Node(com.ardor3d.scenegraph.Node) Mesh(com.ardor3d.scenegraph.Mesh) FloatBuffer(java.nio.FloatBuffer) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3) CullHint(com.ardor3d.scenegraph.hint.CullHint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) Ray3(com.ardor3d.math.Ray3) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Roof(org.concord.energy3d.model.Roof) Spatial(com.ardor3d.scenegraph.Spatial) CancellationException(java.util.concurrent.CancellationException) Foundation(org.concord.energy3d.model.Foundation) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) PickResults(com.ardor3d.intersection.PickResults) HousePart(org.concord.energy3d.model.HousePart)

Example 27 with Mesh

use of com.ardor3d.scenegraph.Mesh in project energy3d by concord-consortium.

the class SolarRadiation method computeOnFresnelReflector.

// unlike PV solar panels, no indirect (ambient or diffuse) radiation should be included in reflection calculation
private void computeOnFresnelReflector(final int minute, final ReadOnlyVector3 directionTowardSun, final FresnelReflector reflector) {
    final int nx = reflector.getNSectionLength();
    final int ny = reflector.getNSectionWidth();
    final Foundation target = reflector.getReceiver();
    if (target != null) {
        final Calendar calendar = Heliodon.getInstance().getCalendar();
        calendar.set(Calendar.HOUR_OF_DAY, (int) ((double) minute / (double) SolarRadiation.MINUTES_OF_DAY * 24.0));
        calendar.set(Calendar.MINUTE, minute % 60);
        reflector.draw();
    }
    // nx*ny*60: nx*ny is to get the unit cell area of the nx*ny grid; 60 is to convert the unit of timeStep from minute to kWh
    final double a = reflector.getModuleWidth() * reflector.getLength() * Scene.getInstance().getTimeStep() / (nx * ny * 60.0);
    final ReadOnlyVector3 normal = reflector.getNormal();
    if (normal == null) {
        throw new RuntimeException("Normal is null");
    }
    final Mesh mesh = reflector.getRadiationMesh();
    MeshDataStore data = onMesh.get(mesh);
    if (data == null) {
        data = initMeshTextureDataOnRectangle(mesh, nx, ny);
    }
    final ReadOnlyVector3 offset = directionTowardSun.multiply(1, null);
    final double dot = normal.dot(directionTowardSun);
    double directRadiation = 0;
    if (dot > 0) {
        directRadiation += calculateDirectRadiation(directionTowardSun, normal);
    }
    final FloatBuffer vertexBuffer = mesh.getMeshData().getVertexBuffer();
    // (0, 0)
    final Vector3 p0 = new Vector3(vertexBuffer.get(3), vertexBuffer.get(4), vertexBuffer.get(5));
    // (1, 0)
    final Vector3 p1 = new Vector3(vertexBuffer.get(6), vertexBuffer.get(7), vertexBuffer.get(8));
    // (0, 1)
    final Vector3 p2 = new Vector3(vertexBuffer.get(0), vertexBuffer.get(1), vertexBuffer.get(2));
    // final Vector3 q0 = mesh.localToWorld(p0, null);
    // final Vector3 q1 = mesh.localToWorld(p1, null);
    // final Vector3 q2 = mesh.localToWorld(p2, null);
    // System.out.println("***" + q0.distance(q1) * Scene.getInstance().getAnnotationScale() + "," + q0.distance(q2) * Scene.getInstance().getAnnotationScale());
    // this is the longer side (supposed to be y)
    final Vector3 u = p1.subtract(p0, null).normalizeLocal();
    // this is the shorter side (supposed to be x)
    final Vector3 v = p2.subtract(p0, null).normalizeLocal();
    // x and y must be swapped to have correct heat map texture, because nx represents rows and ny columns as we call initMeshTextureDataOnRectangle(mesh, nx, ny)
    final double xSpacing = p1.distance(p0) / nx;
    final double ySpacing = p2.distance(p0) / ny;
    final Vector3 absorber = target != null ? target.getSolarReceiverCenter() : null;
    List<Mesh> absorberCollisionMeshes = null;
    if (target != null) {
        absorberCollisionMeshes = new ArrayList<Mesh>();
        for (final HousePart child : target.getChildren()) {
            absorberCollisionMeshes.add((Mesh) child.getRadiationCollisionSpatial());
        }
        final List<Roof> roofs = target.getRoofs();
        if (!roofs.isEmpty()) {
            for (final Roof r : roofs) {
                for (final Spatial roofPart : r.getRoofPartsRoot().getChildren()) {
                    absorberCollisionMeshes.add((Mesh) ((Node) roofPart).getChild(6));
                }
            }
        }
    }
    final int iMinute = minute / Scene.getInstance().getTimeStep();
    final boolean reflectionMapOnly = Scene.getInstance().getOnlyReflectedEnergyInMirrorSolarMap();
    for (int x = 0; x < nx; x++) {
        for (int y = 0; y < ny; y++) {
            if (EnergyPanel.getInstance().isCancelled()) {
                throw new CancellationException();
            }
            final Vector3 u2 = u.multiply(xSpacing * (x + 0.5), null);
            final Vector3 v2 = v.multiply(ySpacing * (y + 0.5), null);
            final ReadOnlyVector3 p = mesh.getWorldTransform().applyForward(p0.add(v2, null).addLocal(u2)).addLocal(offset);
            final Ray3 pickRay = new Ray3(p, directionTowardSun);
            if (dot > 0) {
                final PickResults pickResults = new PrimitivePickResults();
                for (final Spatial spatial : collidables) {
                    if (spatial != mesh) {
                        PickingUtil.findPick(spatial, pickRay, pickResults, false);
                        if (pickResults.getNumber() != 0) {
                            break;
                        }
                    }
                }
                if (pickResults.getNumber() == 0) {
                    // for heat map generation
                    if (!reflectionMapOnly) {
                        data.dailySolarIntensity[x][y] += directRadiation;
                    }
                    // TODO: Edge losses are not considered yet
                    if (absorber != null) {
                        // TODO: This calculation is not exactly accurate as the collision detection assumes that the ray emits from a grid point on the reflector to
                        // the parallel position on the absorber tube -- without considering the actual direction of the reflected light
                        final Vector3 toAbsorber = absorber.subtract(p, null);
                        toAbsorber.setY(0);
                        final Ray3 rayToAbsorber = new Ray3(p, toAbsorber.normalize(null));
                        final PickResults pickResultsToAbsorber = new PrimitivePickResults();
                        for (final Spatial spatial : collidables) {
                            if (spatial != mesh) {
                                if (absorberCollisionMeshes == null || (absorberCollisionMeshes != null && !absorberCollisionMeshes.contains(spatial))) {
                                    PickingUtil.findPick(spatial, rayToAbsorber, pickResultsToAbsorber, false);
                                    if (pickResultsToAbsorber.getNumber() != 0) {
                                        // FIXME: how to stop the ray when it hits the absorber?
                                        break;
                                    }
                                }
                            }
                        }
                        if (pickResultsToAbsorber.getNumber() == 0) {
                            final double r = directRadiation * Atmosphere.getTransmittance(toAbsorber.length() * Scene.getInstance().getAnnotationScale() * 0.001, false);
                            reflector.getSolarPotential()[iMinute] += r * a;
                            if (reflectionMapOnly) {
                                data.dailySolarIntensity[x][y] += r;
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : Calendar(java.util.Calendar) Node(com.ardor3d.scenegraph.Node) Mesh(com.ardor3d.scenegraph.Mesh) FloatBuffer(java.nio.FloatBuffer) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3) CullHint(com.ardor3d.scenegraph.hint.CullHint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) Ray3(com.ardor3d.math.Ray3) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Roof(org.concord.energy3d.model.Roof) Spatial(com.ardor3d.scenegraph.Spatial) CancellationException(java.util.concurrent.CancellationException) Foundation(org.concord.energy3d.model.Foundation) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) PickResults(com.ardor3d.intersection.PickResults) HousePart(org.concord.energy3d.model.HousePart)

Example 28 with Mesh

use of com.ardor3d.scenegraph.Mesh in project energy3d by concord-consortium.

the class SolarRadiation method setupImportedMeshes.

private void setupImportedMeshes() {
    for (final HousePart part : Scene.getInstance().getParts()) {
        if (part instanceof Foundation) {
            final Foundation foundation = (Foundation) part;
            final boolean nonZeroAz = !Util.isZero(foundation.getAzimuth());
            final List<Node> importedNodes = foundation.getImportedNodes();
            if (importedNodes != null) {
                for (final Node node : importedNodes) {
                    for (final Spatial s : node.getChildren()) {
                        final Mesh m = (Mesh) s;
                        final UserData ud = (UserData) m.getUserData();
                        ReadOnlyVector3 normal = ud.getNormal();
                        if (nonZeroAz) {
                            // if the foundation is rotated, rotate the imported meshes, too, but this doesn't alter their original normals
                            // this must be recalculated in case the foundation has been rotated after loading
                            ud.setRotatedNormal(node.getRotation().applyPost(normal, null));
                            normal = ud.getRotatedNormal();
                        }
                        MeshDataStore data = onMesh.get(m);
                        if (data == null) {
                            // initialize mesh solar data and texture
                            data = initMeshTextureData(m, m, normal, true);
                            data.solarPotential = new double[MINUTES_OF_DAY / Scene.getInstance().getTimeStep()];
                        }
                    }
                }
            }
        }
    }
}
Also used : ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Spatial(com.ardor3d.scenegraph.Spatial) UserData(org.concord.energy3d.model.UserData) Node(com.ardor3d.scenegraph.Node) Mesh(com.ardor3d.scenegraph.Mesh) Foundation(org.concord.energy3d.model.Foundation) HousePart(org.concord.energy3d.model.HousePart)

Example 29 with Mesh

use of com.ardor3d.scenegraph.Mesh 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 30 with Mesh

use of com.ardor3d.scenegraph.Mesh in project energy3d by concord-consortium.

the class MeshLib method createMeshes.

public static void createMeshes(final Node root, final ArrayList<GroupData> groups) {
    if (groups.size() != root.getNumberOfChildren()) {
        root.detachAllChildren();
    }
    int meshIndex = 0;
    for (final GroupData group : groups) {
        final Node node;
        final Mesh mesh;
        final Mesh meshWithHoles;
        final BMText label;
        if (meshIndex < root.getNumberOfChildren()) {
            node = (Node) root.getChild(meshIndex);
            mesh = (Mesh) node.getChild(0);
            label = (BMText) node.getChild(3);
            meshWithHoles = (Mesh) node.getChild(6);
            node.getSceneHints().setAllPickingHints(true);
        } else {
            node = new Node("Roof Part #" + meshIndex);
            mesh = new Mesh("Roof Mesh #" + meshIndex);
            meshWithHoles = new Mesh("Roof Mesh with Holes #" + meshIndex);
            mesh.setVisible(false);
            mesh.setModelBound(new BoundingBox());
            meshWithHoles.setModelBound(new BoundingBox());
            meshWithHoles.setRenderState(HousePart.offsetState);
            label = new BMText("Label Text", "", FontManager.getInstance().getPartNumberFont(), Align.South, Justify.Center);
            Util.initHousePartLabel(label);
            final Mesh wireframeMesh = new Line("Roof (wireframe)");
            wireframeMesh.setDefaultColor(ColorRGBA.BLACK);
            wireframeMesh.setModelBound(new BoundingBox());
            wireframeMesh.getMeshData().setVertexBuffer(BufferUtils.createVector3Buffer(10));
            // offset to avoid z-fighting
            wireframeMesh.setTranslation(group.key.multiply(0.001, null));
            final Line dashLineMesh = new Line("Roof (dash line)");
            dashLineMesh.setStipplePattern((short) 0xFF00);
            dashLineMesh.setVisible(false);
            dashLineMesh.setModelBound(new BoundingBox());
            final Node sizeAnnotation = new Node("Roof Size Annot");
            final Node angleAnnotation = new Node("Roof Angle Annot");
            // disable picking for all except mesh
            Util.disablePickShadowLight(sizeAnnotation);
            Util.disablePickShadowLight(angleAnnotation);
            Util.disablePickShadowLight(wireframeMesh);
            Util.disablePickShadowLight(dashLineMesh);
            // meshWithHoles.getSceneHints().setAllPickingHints(false);
            node.attachChild(mesh);
            node.attachChild(sizeAnnotation);
            node.attachChild(angleAnnotation);
            node.attachChild(label);
            node.attachChild(wireframeMesh);
            node.attachChild(dashLineMesh);
            node.attachChild(meshWithHoles);
            root.attachChild(node);
        }
        node.getSceneHints().setCullHint(CullHint.Never);
        CollisionTreeManager.getInstance().removeCollisionTree(mesh);
        CollisionTreeManager.getInstance().removeCollisionTree(meshWithHoles);
        final Vector3 normal = group.key;
        node.setUserData(normal);
        final FloatBuffer buf = BufferUtils.createVector3Buffer(group.vertices.size());
        mesh.getMeshData().setVertexBuffer(buf);
        final Vector3 center = new Vector3();
        for (final ReadOnlyVector3 v : group.vertices) {
            buf.put(v.getXf()).put(v.getYf()).put(v.getZf());
            center.addLocal(v);
        }
        center.multiplyLocal(1.0 / group.vertices.size());
        label.setTranslation(center.add(normal.multiply(0.1, null), null));
        mesh.updateModelBound();
        meshIndex++;
    }
}
Also used : Line(com.ardor3d.scenegraph.Line) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Node(com.ardor3d.scenegraph.Node) BoundingBox(com.ardor3d.bounding.BoundingBox) Mesh(com.ardor3d.scenegraph.Mesh) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3) FloatBuffer(java.nio.FloatBuffer) BMText(com.ardor3d.ui.text.BMText) CullHint(com.ardor3d.scenegraph.hint.CullHint) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point)

Aggregations

Mesh (com.ardor3d.scenegraph.Mesh)69 Spatial (com.ardor3d.scenegraph.Spatial)36 ReadOnlyVector3 (com.ardor3d.math.type.ReadOnlyVector3)33 Node (com.ardor3d.scenegraph.Node)31 CullHint (com.ardor3d.scenegraph.hint.CullHint)28 Vector3 (com.ardor3d.math.Vector3)25 FloatBuffer (java.nio.FloatBuffer)18 TPoint (org.poly2tri.triangulation.point.TPoint)16 Line (com.ardor3d.scenegraph.Line)15 ArrayList (java.util.ArrayList)15 BoundingBox (com.ardor3d.bounding.BoundingBox)12 Point (org.poly2tri.geometry.primitives.Point)12 HousePart (org.concord.energy3d.model.HousePart)11 OrientedBoundingBox (com.ardor3d.bounding.OrientedBoundingBox)10 PickResults (com.ardor3d.intersection.PickResults)10 PrimitivePickResults (com.ardor3d.intersection.PrimitivePickResults)10 Ray3 (com.ardor3d.math.Ray3)10 Foundation (org.concord.energy3d.model.Foundation)10 ColorRGBA (com.ardor3d.math.ColorRGBA)8 Calendar (java.util.Calendar)8