Search in sources :

Example 16 with TriangleMesh

use of javafx.scene.shape.TriangleMesh in project FXyzLib by Birdasaur.

the class TorusMesh method createTorus.

private TriangleMesh createTorus(int radiusDivisions, int tubeDivisions, float radius, float tRadius, float tubeStartAngle, float xOffset, float yOffset, float zOffset) {
    int numVerts = tubeDivisions * radiusDivisions;
    int faceCount = numVerts * 2;
    float[] points = new float[numVerts * 3], texCoords = new float[numVerts * 2];
    int[] faces = new int[faceCount * 6];
    int pointIndex = 0, texIndex = 0, faceIndex = 0;
    float tubeFraction = 1.0f / tubeDivisions;
    float radiusFraction = 1.0f / radiusDivisions;
    float x, y, z;
    int p0 = 0, p1 = 0, p2 = 0, p3 = 0, t0 = 0, t1 = 0, t2 = 0, t3 = 0;
    // create points
    for (int tubeIndex = 0; tubeIndex < tubeDivisions; tubeIndex++) {
        float radian = tubeStartAngle + tubeFraction * tubeIndex * 2.0f * 3.141592653589793f;
        for (int radiusIndex = 0; radiusIndex < radiusDivisions; radiusIndex++) {
            float localRadian = radiusFraction * (radiusIndex) * 2.0f * 3.141592653589793f;
            points[pointIndex + 0] = x = (radius + tRadius * ((float) Math.cos(radian))) * ((float) Math.cos(localRadian) + xOffset);
            points[pointIndex + 1] = y = (radius + tRadius * ((float) Math.cos(radian))) * ((float) Math.sin(localRadian) + yOffset);
            points[pointIndex + 2] = z = (tRadius * (float) Math.sin(radian) * zOffset);
            pointIndex += 3;
            float r = radiusIndex < tubeDivisions ? tubeFraction * radiusIndex * 2.0F * 3.141592653589793f : 0.0f;
            texCoords[texIndex] = (0.5F + (float) (Math.sin(r) * 0.5D));
            texCoords[texIndex + 1] = ((float) (Math.cos(r) * 0.5D) + 0.5F);
            texIndex += 2;
        }
    }
    // create faces
    for (int point = 0; point < (tubeDivisions); point++) {
        for (int crossSection = 0; crossSection < (radiusDivisions); crossSection++) {
            p0 = point * radiusDivisions + crossSection;
            p1 = p0 >= 0 ? p0 + 1 : p0 - (radiusDivisions);
            p1 = p1 % (radiusDivisions) != 0 ? p0 + 1 : p0 - (radiusDivisions - 1);
            p2 = (p0 + radiusDivisions) < ((tubeDivisions * radiusDivisions)) ? p0 + radiusDivisions : p0 - (tubeDivisions * radiusDivisions) + radiusDivisions;
            p3 = p2 < ((tubeDivisions * radiusDivisions) - 1) ? p2 + 1 : p2 - (tubeDivisions * radiusDivisions) + 1;
            p3 = p3 % (radiusDivisions) != 0 ? p2 + 1 : p2 - (radiusDivisions - 1);
            t0 = point * (radiusDivisions) + crossSection;
            t1 = t0 >= 0 ? t0 + 1 : t0 - (radiusDivisions);
            t1 = t1 % (radiusDivisions) != 0 ? t0 + 1 : t0 - (radiusDivisions - 1);
            t2 = (t0 + radiusDivisions) < ((tubeDivisions * radiusDivisions)) ? t0 + radiusDivisions : t0 - (tubeDivisions * radiusDivisions) + radiusDivisions;
            t3 = t2 < ((tubeDivisions * radiusDivisions) - 1) ? t2 + 1 : t2 - (tubeDivisions * radiusDivisions) + 1;
            t3 = t3 % (radiusDivisions) != 0 ? t2 + 1 : t2 - (radiusDivisions - 1);
            try {
                faces[faceIndex] = (p2);
                faces[faceIndex + 1] = (t3);
                faces[faceIndex + 2] = (p0);
                faces[faceIndex + 3] = (t2);
                faces[faceIndex + 4] = (p1);
                faces[faceIndex + 5] = (t0);
                faceIndex += 6;
                faces[faceIndex] = (p2);
                faces[faceIndex + 1] = (t3);
                faces[faceIndex + 2] = (p1);
                faces[faceIndex + 3] = (t0);
                faces[faceIndex + 4] = (p3);
                faces[faceIndex + 5] = (t1);
                faceIndex += 6;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    TriangleMesh localTriangleMesh = new TriangleMesh();
    localTriangleMesh.getPoints().setAll(points);
    localTriangleMesh.getTexCoords().setAll(texCoords);
    localTriangleMesh.getFaces().setAll(faces);
    return localTriangleMesh;
}
Also used : TriangleMesh(javafx.scene.shape.TriangleMesh)

Example 17 with TriangleMesh

use of javafx.scene.shape.TriangleMesh in project FXyzLib by Birdasaur.

the class TriangulatedMesh method createMesh.

private TriangleMesh createMesh(int level) {
    TriangleMesh m0 = null;
    if (level > 0) {
        m0 = createMesh(level - 1);
    }
    if (level == 0) {
        // check for duplicates or too close
        List<Integer> duplicates = IntStream.range(0, pointsExterior.size()).boxed().filter(i -> pointsExterior.get(i).substract(pointsExterior.get(i == pointsExterior.size() - 1 ? 0 : i + 1)).magnitude() < 100 * EPSILON).map(i -> i).collect(Collectors.toList());
        duplicates.stream().sorted(Collections.reverseOrder()).forEach(i -> pointsExterior.remove(i.intValue()));
        List<PolygonPoint> list = pointsExterior.stream().map(p -> new PolygonPoint(p.x, p.y)).collect(Collectors.toList());
        Polygon poly = new Polygon(list);
        if (bounds.get() != null) {
            maxX = bounds.get().getMaxX();
            minX = bounds.get().getMinX();
            maxY = bounds.get().getMaxY();
            minY = bounds.get().getMinY();
        } else {
            maxX = pointsExterior.stream().mapToDouble(p -> p.x).max().getAsDouble();
            maxY = pointsExterior.stream().mapToDouble(p -> p.y).max().getAsDouble();
            minX = pointsExterior.stream().mapToDouble(p -> p.x).min().getAsDouble();
            minY = pointsExterior.stream().mapToDouble(p -> p.y).min().getAsDouble();
        }
        double rad = getHoleRadius();
        if (pointsHoles != null) {
            steinerPoints = 0;
            numHoles = pointsHoles.size();
            // holes
            pointsHoles.forEach(pHole -> {
                // hole
                List<PolygonPoint> hole = pHole.stream().distinct().map(p -> new PolygonPoint(p.x, p.y)).collect(Collectors.toList());
                holePoints.add(hole.size());
                Polygon polyIn = new Polygon(hole);
                poly.addHole(polyIn);
                holes.add(hole);
            });
        } else if (rad > 0d) {
            steinerPoints = 0;
            numHoles = 1;
            int num = 200;
            holePoints.add(num);
            // circular hole
            List<PolygonPoint> hole = IntStream.range(0, num).mapToObj(i -> new PolygonPoint((maxX + minX) / 2d + rad * Math.cos((num - i) * 2d * Math.PI / num), (maxY + minY) / 2d + rad * Math.sin((num - i) * 2d * Math.PI / num))).collect(Collectors.toList());
            Polygon polyIn = new Polygon(hole);
            poly.addHole(polyIn);
            holes.add(hole);
        } else {
            double radSteiner = Math.sqrt(Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)) / 8d;
            // steiner points
            steiner = IntStream.range(0, steinerPoints).mapToObj(i -> new PolygonPoint((maxX + minX) / 2d + radSteiner * Math.cos(i * 2d * Math.PI / steinerPoints), (maxY + minY) / 2d + radSteiner * Math.sin(i * 2d * Math.PI / steinerPoints))).collect(Collectors.toList());
            poly.addSteinerPoints(steiner);
        }
        PolygonSet ps = new PolygonSet(poly);
        Poly2Tri.triangulate(ps);
        Polygon polRes = ps.getPolygons().get(0);
        List<DelaunayTriangle> tri = polRes.getTriangles();
        points1 = polRes.getPoints();
        extPoints = points1.size();
        if (pointsHoles != null || rad > 0d) {
            holes.forEach(hole -> hole.forEach(points1::add));
        } else {
            steiner.forEach(points1::add);
        }
        int totalHolePoints = holePoints.stream().reduce(0, Integer::sum);
        int numPoints = extPoints + steinerPoints + totalHolePoints;
        FloatCollector pointsBottom = points1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY(), 0d)).collect(() -> new FloatCollector(points1.size() * 3), FloatCollector::add, FloatCollector::join);
        FloatCollector pointsTop = points1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY(), height.get())).collect(() -> new FloatCollector(points1.size() * 3), FloatCollector::add, FloatCollector::join);
        pointsBottom.join(pointsTop);
        points0 = pointsBottom.toArray();
        numVertices = points0.length / 3;
        FloatCollector texBottom = points1.stream().flatMapToDouble(p -> DoubleStream.of((p.getX() - minX) / (maxX - minX), (p.getY() - minY) / (maxY - minY))).collect(() -> new FloatCollector(points1.size() * 2), FloatCollector::add, FloatCollector::join);
        FloatCollector texTop = points1.stream().flatMapToDouble(p -> DoubleStream.of((p.getX() - minX) / (maxX - minX), (p.getY() - minY) / (maxY - minY))).collect(() -> new FloatCollector(points1.size() * 2), FloatCollector::add, FloatCollector::join);
        texBottom.join(texTop);
        texCoord0 = texBottom.toArray();
        numTexCoords = texCoord0.length / 2;
        texCoord1 = IntStream.range(0, numTexCoords).mapToObj(i -> new Point2D(texCoord0[2 * i], texCoord0[2 * i + 1])).collect(Collectors.toList());
        List<int[]> listIndices = tri.stream().map((DelaunayTriangle t) -> {
            int[] pIndex = new int[3];
            for (int j = 0; j < 3; j++) {
                final TriangulationPoint dt = t.points[j];
                int[] toArray = IntStream.range(0, points1.size()).filter(i -> points1.get(i).equals(dt)).toArray();
                if (toArray.length > 0) {
                    pIndex[j] = toArray[0];
                } else {
                    System.out.println("Error " + points1);
                }
            }
            return pIndex;
        }).collect(Collectors.toList());
        // faces
        // base
        IntStream streamBottom = listIndices.stream().map(i -> IntStream.of(i[0], i[0], i[2], i[2], i[1], i[1])).flatMapToInt(i -> i);
        // top
        IntStream streamTop = listIndices.stream().map(i -> IntStream.of(numPoints + i[0], numPoints + i[0], numPoints + i[1], numPoints + i[1], numPoints + i[2], numPoints + i[2])).flatMapToInt(i -> i);
        // vertical, exterior
        IntStream streamExtWalls = IntStream.range(0, extPoints - 1).mapToObj(i -> IntStream.of(i, i, i + 1, i + 1, i + 1 + numPoints, i + 1 + numPoints, i, i, i + 1 + numPoints, i + 1 + numPoints, i + numPoints, i + numPoints)).flatMapToInt(i -> i);
        // vertical, exterior, close polygon
        IntStream streamExtWallsClose = IntStream.of(extPoints - 1, extPoints - 1, 0, 0, 0 + numPoints, 0 + numPoints, extPoints - 1, extPoints - 1, 0 + numPoints, 0 + numPoints, numPoints + extPoints - 1, numPoints + extPoints - 1);
        if (totalHolePoints > 0) {
            // vertical, interior
            // holes
            int acuHolePoints0 = extPoints + steinerPoints, acuHolePoints1;
            IntStream streamIntWalls = IntStream.empty();
            for (List<PolygonPoint> hole : holes) {
                acuHolePoints1 = acuHolePoints0 + hole.size() - 1;
                IntStream streamIntWallsHole = IntStream.range(acuHolePoints0, acuHolePoints1).mapToObj(i -> IntStream.of(i, i, i + 1 + numPoints, i + 1 + numPoints, i + 1, i + 1, i, i, i + numPoints, i + numPoints, i + 1 + numPoints, i + 1 + numPoints)).flatMapToInt(i -> i);
                streamIntWalls = IntStream.concat(streamIntWalls, streamIntWallsHole);
                acuHolePoints0 = acuHolePoints1 + 1;
            }
            // vertical, interior, close holes
            // holes
            acuHolePoints0 = extPoints + steinerPoints;
            IntStream streamIntWallsClose = IntStream.empty();
            for (List<PolygonPoint> hole : holes) {
                acuHolePoints1 = acuHolePoints0 + hole.size() - 1;
                IntStream streamIntWallsCloseHole = IntStream.of(acuHolePoints1, acuHolePoints1, numPoints + acuHolePoints0, numPoints + acuHolePoints0, acuHolePoints0, acuHolePoints0, acuHolePoints1, acuHolePoints1, numPoints + acuHolePoints1, numPoints + acuHolePoints1, numPoints + acuHolePoints0, numPoints + acuHolePoints0);
                streamIntWallsClose = IntStream.concat(streamIntWallsClose, streamIntWallsCloseHole);
                acuHolePoints0 = acuHolePoints1 + 1;
            }
            faces0 = IntStream.concat(streamBottom, IntStream.concat(streamTop, IntStream.concat(streamExtWalls, IntStream.concat(streamExtWallsClose, IntStream.concat(streamIntWalls, streamIntWallsClose))))).toArray();
        } else {
            faces0 = IntStream.concat(streamBottom, IntStream.concat(streamTop, IntStream.concat(streamExtWalls, streamExtWallsClose))).toArray();
        }
        numFaces = faces0.length / 6;
    } else if (m0 != null) {
        points0 = new float[numVertices * m0.getPointElementSize()];
        m0.getPoints().toArray(points0);
        texCoord0 = new float[numTexCoords * m0.getTexCoordElementSize()];
        m0.getTexCoords().toArray(texCoord0);
        faces0 = new int[numFaces * m0.getFaceElementSize()];
        m0.getFaces().toArray(faces0);
    }
    List<Point3D> points1 = IntStream.range(0, numVertices).mapToObj(i -> new Point3D(points0[3 * i], points0[3 * i + 1], points0[3 * i + 2])).collect(Collectors.toList());
    texCoord1 = IntStream.range(0, numTexCoords).mapToObj(i -> new Point2D(texCoord0[2 * i], texCoord0[2 * i + 1])).collect(Collectors.toList());
    List<Face3> faces1 = IntStream.range(0, numFaces).mapToObj(i -> new Face3(faces0[6 * i], faces0[6 * i + 2], faces0[6 * i + 4])).collect(Collectors.toList());
    index.set(points1.size());
    map.clear();
    listFaces.clear();
    listVertices.clear();
    listVertices.addAll(points1);
    faces1.forEach(face -> {
        int v1 = face.p0;
        int v2 = face.p1;
        int v3 = face.p2;
        if (level > 0) {
            int a = getMiddle(v1, points1.get(v1), v2, points1.get(v2));
            int b = getMiddle(v2, points1.get(v2), v3, points1.get(v3));
            int c = getMiddle(v3, points1.get(v3), v1, points1.get(v1));
            listFaces.add(new Face3(v1, a, c));
            listFaces.add(new Face3(v2, b, a));
            listFaces.add(new Face3(v3, c, b));
            listFaces.add(new Face3(a, b, c));
        } else {
            listFaces.add(new Face3(v1, v2, v3));
        }
    });
    map.clear();
    numVertices = listVertices.size();
    numFaces = listFaces.size();
    List<Face3> textures1 = IntStream.range(0, faces0.length / 6).mapToObj(i -> new Face3(faces0[6 * i + 1], faces0[6 * i + 3], faces0[6 * i + 5])).collect(Collectors.toList());
    index.set(texCoord1.size());
    listTextures.clear();
    textures1.forEach(face -> {
        int v1 = face.p0;
        int v2 = face.p1;
        int v3 = face.p2;
        if (level > 0) {
            int a = getMiddle(v1, texCoord1.get(v1), v2, texCoord1.get(v2));
            int b = getMiddle(v2, texCoord1.get(v2), v3, texCoord1.get(v3));
            int c = getMiddle(v3, texCoord1.get(v3), v1, texCoord1.get(v1));
            listTextures.add(new Face3(v1, a, c));
            listTextures.add(new Face3(v2, b, a));
            listTextures.add(new Face3(v3, c, b));
            listTextures.add(new Face3(a, b, c));
        } else {
            listTextures.add(new Face3(v1, v2, v3));
        }
    });
    map.clear();
    texCoord0 = texCoord1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY())).collect(() -> new FloatCollector(texCoord1.size() * 2), FloatCollector::add, FloatCollector::join).toArray();
    numTexCoords = texCoord0.length / 2;
    textureCoords = texCoord0;
    if (level == getLevel()) {
        areaMesh.setWidth(maxX - minX);
        areaMesh.setHeight(maxY - minY);
        rectMesh.setWidth((int) Math.sqrt(texCoord0.length));
        rectMesh.setHeight(texCoord0.length / ((int) Math.sqrt(texCoord0.length)));
        smoothingGroups = getSmoothingGroups(listVertices, listFaces);
    }
    return createMesh();
}
Also used : IntStream(java.util.stream.IntStream) HashMap(java.util.HashMap) DoubleProperty(javafx.beans.property.DoubleProperty) IntegerProperty(javafx.beans.property.IntegerProperty) CullFace(javafx.scene.shape.CullFace) TriangleMesh(javafx.scene.shape.TriangleMesh) ArrayList(java.util.ArrayList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelaunayTriangle(org.poly2tri.triangulation.delaunay.DelaunayTriangle) SimpleIntegerProperty(javafx.beans.property.SimpleIntegerProperty) Polygon(org.poly2tri.polygon.Polygon) Point2D(javafx.geometry.Point2D) ObjectProperty(javafx.beans.property.ObjectProperty) FloatCollector(org.fxyz.utils.FloatCollector) PolygonSet(org.poly2tri.polygon.PolygonSet) DrawMode(javafx.scene.shape.DrawMode) Collectors(java.util.stream.Collectors) DoubleStream(java.util.stream.DoubleStream) Poly2Tri(org.poly2tri.Poly2Tri) List(java.util.List) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) DepthTest(javafx.scene.DepthTest) Face3(org.fxyz.geometry.Face3) SimpleDoubleProperty(javafx.beans.property.SimpleDoubleProperty) TriangulationPoint(org.poly2tri.triangulation.TriangulationPoint) Collections(java.util.Collections) PolygonPoint(org.poly2tri.polygon.PolygonPoint) Point3D(org.fxyz.geometry.Point3D) Bounds(javafx.geometry.Bounds) TriangulationPoint(org.poly2tri.triangulation.TriangulationPoint) TriangleMesh(javafx.scene.shape.TriangleMesh) FloatCollector(org.fxyz.utils.FloatCollector) DelaunayTriangle(org.poly2tri.triangulation.delaunay.DelaunayTriangle) PolygonPoint(org.poly2tri.polygon.PolygonPoint) PolygonSet(org.poly2tri.polygon.PolygonSet) TriangulationPoint(org.poly2tri.triangulation.TriangulationPoint) PolygonPoint(org.poly2tri.polygon.PolygonPoint) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Point2D(javafx.geometry.Point2D) Point3D(org.fxyz.geometry.Point3D) ArrayList(java.util.ArrayList) List(java.util.List) Polygon(org.poly2tri.polygon.Polygon) IntStream(java.util.stream.IntStream) Face3(org.fxyz.geometry.Face3)

Example 18 with TriangleMesh

use of javafx.scene.shape.TriangleMesh in project FXyzLib by Birdasaur.

the class ScatterPlotMesh method setXYZData.

public void setXYZData(ArrayList<Double> xData, ArrayList<Double> yData, ArrayList<Double> zData) {
    xAxisData = xData;
    yAxisData = yData;
    zAxisData = zData;
    getChildren().clear();
    // for now we will always default to x axis
    // later we could maybe dynamically determine the smallest axis and then
    // uses 0's for the other axes that are larger.
    ArrayList<Point3D> point3DList = new ArrayList<>();
    for (int i = 0; i < xAxisData.size(); i++) {
        // some safety checks for array sizes
        double translateY = 0.0;
        double translateZ = 0.0;
        if (!yAxisData.isEmpty() && yAxisData.size() > i)
            translateY = yAxisData.get(i);
        if (!zAxisData.isEmpty() && zAxisData.size() > i)
            translateZ = zAxisData.get(i);
        setTranslateX(xAxisData.get(i));
        // Convert to Floats and build list of adjusted points
        point3DList.add(new Point3D(new Float(xAxisData.get(i)), new Float(translateY), new Float(translateZ)));
        float width = 1;
        final TriangleMesh mesh = new TriangleMesh();
        // This extra point allows us to build triangles later
        for (Point3D point : point3DList) {
            // Rear points
            // top right rear point
            mesh.getPoints().addAll(point.x + width, point.y + width, point.z + width);
            // top left rear point
            mesh.getPoints().addAll(point.x - width, point.y + width, point.z + width);
            // bottom right rear point
            mesh.getPoints().addAll(point.x + width, point.y - width, point.z + width);
            // bottom left rear point
            mesh.getPoints().addAll(point.x - width, point.y - width, point.z + width);
            // Front points
            // top right front point
            mesh.getPoints().addAll(point.x + width, point.y + width, point.z - width);
            // top left front point
            mesh.getPoints().addAll(point.x - width, point.y + width, point.z - width);
            // bottom right front point
            mesh.getPoints().addAll(point.x + width, point.y - width, point.z - width);
            // bottom left front point
            mesh.getPoints().addAll(point.x - width, point.y - width, point.z - width);
        }
        // add dummy Texture Coordinate
        mesh.getTexCoords().addAll(0, 0);
        // Now generate nodes for each point
        for (int p = 8; p < point3DList.size() * 7; p += 8) {
            // add each segment
            // Wind the next 8 vertices as a cube.  The cube itself will represent the data
            // Vertices wound counter-clockwise which is the default front face of any Triangle
            // Rear triangle faces should be wound clockwise to face away from center
            // TRR,BLR,BRR
            mesh.getFaces().addAll(p, 0, p + 3, 0, p + 2, 0);
            // BLR,TRR,TLR
            mesh.getFaces().addAll(p + 3, 0, p, 0, p + 1, 0);
            // left side faces
            // TLR,TLF,BLR
            mesh.getFaces().addAll(p + 1, 0, p + 5, 0, p + 3, 0);
            // TLF,BLR,BLF
            mesh.getFaces().addAll(p + 5, 0, p + 7, 0, p + 3, 0);
            // front side faces
            // TLF,BLF,TLR
            mesh.getFaces().addAll(p + 5, 0, p + 7, 0, p + 4, 0);
            // TRF,BLF,BRF
            mesh.getFaces().addAll(p + 4, 0, p + 7, 0, p + 6, 0);
            // front side faces
            // TRF,BRF,BRR
            mesh.getFaces().addAll(p + 4, 0, p + 6, 0, p + 2, 0);
            // TRF,BRR,TRR
            mesh.getFaces().addAll(p + 4, 0, p + 2, 0, p, 0);
            // Top faces
            // TRR,TLR,TRF
            mesh.getFaces().addAll(p, 0, p + 1, 0, p + 3, 0);
            // TLR,TLF,TRF
            mesh.getFaces().addAll(p + 1, 0, p + 5, 0, p + 3, 0);
            // bottom faces
            // BLR,BLF,BRF
            mesh.getFaces().addAll(p + 3, 0, p + 7, 0, p + 6, 0);
            // BLR,BRF,BRR
            mesh.getFaces().addAll(p + 3, 0, p + 6, 0, p + 2, 0);
        }
        // Need to add the mesh to a MeshView before adding to our 3D scene
        MeshView meshView = new MeshView(mesh);
        // Fill so that the line shows width
        meshView.setDrawMode(DrawMode.FILL);
        Color hsb = Color.hsb((new Double(i) / 12) * 360, 1.0, 1.0, 0.5);
        PhongMaterial material = new PhongMaterial(hsb);
        material.setDiffuseColor(hsb);
        material.setSpecularColor(hsb);
        meshView.setMaterial(material);
        // Make sure you Cull the Back so that no black shows through
        meshView.setCullFace(CullFace.BACK);
        // //Add some ambient light so folks can see it
        // Group line = new Group();
        // AmbientLight light = new AmbientLight(Color.WHITE);
        // light.getScope().add(meshView);
        // line.getChildren().add(light);
        // line.getChildren().add(meshView);
        getChildren().addAll(meshView);
    }
}
Also used : TriangleMesh(javafx.scene.shape.TriangleMesh) Point3D(org.fxyz.geometry.Point3D) Color(javafx.scene.paint.Color) ArrayList(java.util.ArrayList) PhongMaterial(javafx.scene.paint.PhongMaterial) MeshView(javafx.scene.shape.MeshView)

Example 19 with TriangleMesh

use of javafx.scene.shape.TriangleMesh in project FXyzLib by Birdasaur.

the class CapsuleMesh method createCapsule.

static TriangleMesh createCapsule(int sphereDivisions, float radius, float height) {
    TriangleMesh m = new TriangleMesh();
    sphereDivisions = correctDivisions(sphereDivisions);
    final int halfDivisions = sphereDivisions / 2;
    final float fDivisions = 1.f / sphereDivisions;
    final int numPoints = sphereDivisions * (halfDivisions - 1) + 2;
    final int numTexCoords = (sphereDivisions + 1) * (halfDivisions - 1) + sphereDivisions * 2;
    final int numFaces = sphereDivisions * (halfDivisions - 2) * 2 + sphereDivisions * 2;
    float[] points = new float[numPoints * m.getPointElementSize()];
    float[] texCoords = new float[numTexCoords * m.getTexCoordElementSize()];
    int[] faces = new int[numFaces * m.getFaceElementSize()];
    int pointIndex = 0, texIndex = 0;
    float x, y, z;
    for (int i = 0; i < halfDivisions - 1; ++i) {
        float va = fDivisions * (i + 1 - halfDivisions / 2) * 2 * (float) Math.PI;
        float hdY = (float) Math.sin(va);
        float hdX = (float) Math.cos(va);
        float thetaY = 0.5f + hdY * 0.5f;
        for (int point = 0; point < sphereDivisions; ++point) {
            double localTheta = fDivisions * point * 2 * (float) Math.PI;
            float ly = (float) Math.sin(localTheta);
            float lx = (float) Math.cos(localTheta);
            if (i >= (halfDivisions - 1) / 2) {
                // X
                points[pointIndex + 0] = x = ly * hdX * (radius);
                // Y
                points[pointIndex + 1] = y = hdY * (radius) + height;
                // Z
                points[pointIndex + 2] = z = lx * hdX * radius;
            } else {
                // X
                points[pointIndex + 0] = x = ly * hdX * (radius);
                // Y
                points[pointIndex + 1] = y = hdY * (radius);
                // Z
                points[pointIndex + 2] = z = lx * hdX * radius;
            }
            texCoords[texIndex + 0] = 1 - fDivisions * point;
            texCoords[texIndex + 1] = thetaY;
            pointIndex += 3;
            texIndex += 2;
        }
        texCoords[texIndex + 0] = 0;
        texCoords[texIndex + 1] = thetaY;
        texIndex += 2;
    }
    points[pointIndex + 0] = 0;
    points[pointIndex + 1] = -(radius);
    points[pointIndex + 2] = 0;
    points[pointIndex + 3] = 0;
    points[pointIndex + 4] = radius + height;
    points[pointIndex + 5] = 0;
    pointIndex += 6;
    int pS = (halfDivisions - 1) * sphereDivisions;
    float textureDelta = 1.f / 256;
    for (int i = 0; i < sphereDivisions; ++i) {
        texCoords[texIndex + 0] = fDivisions * (0.5f + i);
        texCoords[texIndex + 1] = textureDelta;
        texIndex += 2;
    }
    for (int i = 0; i < sphereDivisions; ++i) {
        texCoords[texIndex + 0] = fDivisions * (0.5f + i);
        texCoords[texIndex + 1] = 1 - textureDelta;
        texIndex += 2;
    }
    int faceIndex = 0;
    for (int i = 0; i < halfDivisions - 2; ++i) {
        for (int j = 0; j < sphereDivisions; ++j) {
            int p0 = i * sphereDivisions + j;
            int p1 = p0 + 1;
            int p2 = p0 + sphereDivisions;
            int p3 = p1 + sphereDivisions;
            int t0 = p0 + i;
            int t1 = t0 + 1;
            int t2 = t0 + (sphereDivisions + 1);
            int t3 = t1 + (sphereDivisions + 1);
            // add p0, p1, p2
            faces[faceIndex + 0] = p0;
            faces[faceIndex + 1] = t0;
            faces[faceIndex + 2] = p1 % sphereDivisions == 0 ? p1 - sphereDivisions : p1;
            faces[faceIndex + 3] = t1;
            faces[faceIndex + 4] = p2;
            faces[faceIndex + 5] = t2;
            faceIndex += 6;
            // add p3, p2, p1
            faces[faceIndex + 0] = p3 % sphereDivisions == 0 ? p3 - sphereDivisions : p3;
            faces[faceIndex + 1] = t3;
            faces[faceIndex + 2] = p2;
            faces[faceIndex + 3] = t2;
            faces[faceIndex + 4] = p1 % sphereDivisions == 0 ? p1 - sphereDivisions : p1;
            faces[faceIndex + 5] = t1;
            faceIndex += 6;
        }
    }
    int p0 = pS;
    int tB = (halfDivisions - 1) * (sphereDivisions + 1);
    for (int i = 0; i < sphereDivisions; ++i) {
        int p2 = i, p1 = i + 1, t0 = tB + i;
        faces[faceIndex + 0] = p0;
        faces[faceIndex + 1] = t0;
        faces[faceIndex + 2] = p1 == sphereDivisions ? 0 : p1;
        faces[faceIndex + 3] = p1;
        faces[faceIndex + 4] = p2;
        faces[faceIndex + 5] = p2;
        faceIndex += 6;
    }
    p0 = p0 + 1;
    tB = tB + sphereDivisions;
    int pB = (halfDivisions - 2) * sphereDivisions;
    for (int i = 0; i < sphereDivisions; ++i) {
        int p1 = pB + i, p2 = pB + i + 1, t0 = tB + i;
        int t1 = (halfDivisions - 2) * (sphereDivisions + 1) + i, t2 = t1 + 1;
        faces[faceIndex + 0] = p0;
        faces[faceIndex + 1] = t0;
        faces[faceIndex + 2] = p1;
        faces[faceIndex + 3] = t1;
        faces[faceIndex + 4] = p2 % sphereDivisions == 0 ? p2 - sphereDivisions : p2;
        faces[faceIndex + 5] = t2;
        faceIndex += 6;
    }
    m.getPoints().setAll(points);
    m.getTexCoords().setAll(texCoords);
    m.getFaces().setAll(faces);
    return m;
}
Also used : TriangleMesh(javafx.scene.shape.TriangleMesh)

Example 20 with TriangleMesh

use of javafx.scene.shape.TriangleMesh in project FXyzLib by Birdasaur.

the class OctahedronMesh method createOctahedron.

private TriangleMesh createOctahedron(double hypotenuse, double height) {
    TriangleMesh mesh = new TriangleMesh();
    float hy = (float) hypotenuse;
    float he = (float) height;
    mesh.getPoints().addAll(// point O
    0, // point O
    0, // point O
    0, // point A
    0, // point A
    he, // point A
    -hy / 2, // point B
    -hy / 2, // point B
    he, // point B
    0, // point C
    hy / 2, // point C
    he, // point C
    0, // point D
    0, // point D
    he, // point D
    hy / 2, // point E
    0, // point E
    2 * he, // point E
    0);
    mesh.getTexCoords().addAll(0, 0);
    mesh.getFaces().addAll(// O-B-A
    0, // O-B-A
    0, // O-B-A
    2, // O-B-A
    0, // O-B-A
    1, // O-B-A
    0, // O-A-C
    0, // O-A-C
    0, // O-A-C
    1, // O-A-C
    0, // O-A-C
    3, // O-A-C
    0, // O-C-D
    0, // O-C-D
    0, // O-C-D
    3, // O-C-D
    0, // O-C-D
    4, // O-C-D
    0, // O-D-B
    0, // O-D-B
    0, // O-D-B
    4, // O-D-B
    0, // O-D-B
    2, // O-D-B
    0, // D-A-B
    4, // D-A-B
    0, // D-A-B
    1, // D-A-B
    0, // D-A-B
    2, // D-A-B
    0, // D-C-A
    4, // D-C-A
    0, // D-C-A
    3, // D-C-A
    0, // D-C-A
    1, // D-C-A
    0, // E-B-A
    5, // E-B-A
    0, // E-B-A
    2, // E-B-A
    0, // E-B-A
    1, // E-B-A
    0, // E-A-C
    5, // E-A-C
    0, // E-A-C
    1, // E-A-C
    0, // E-A-C
    3, // E-A-C
    0, // E-C-D
    5, // E-C-D
    0, // E-C-D
    3, // E-C-D
    0, // E-C-D
    4, // E-C-D
    0, // E-D-B
    5, // E-D-B
    0, // E-D-B
    4, // E-D-B
    0, // E-D-B
    2, // E-D-B
    0);
    return mesh;
}
Also used : TriangleMesh(javafx.scene.shape.TriangleMesh)

Aggregations

TriangleMesh (javafx.scene.shape.TriangleMesh)22 Point3D (org.fxyz.geometry.Point3D)9 List (java.util.List)8 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)8 IntStream (java.util.stream.IntStream)8 DrawMode (javafx.scene.shape.DrawMode)8 Collectors (java.util.stream.Collectors)7 IntegerProperty (javafx.beans.property.IntegerProperty)7 SimpleIntegerProperty (javafx.beans.property.SimpleIntegerProperty)7 DepthTest (javafx.scene.DepthTest)7 CullFace (javafx.scene.shape.CullFace)7 HashMap (java.util.HashMap)6 DoubleStream (java.util.stream.DoubleStream)6 DoubleProperty (javafx.beans.property.DoubleProperty)6 SimpleDoubleProperty (javafx.beans.property.SimpleDoubleProperty)6 Point2D (javafx.geometry.Point2D)6 Face3 (org.fxyz.geometry.Face3)6 FloatCollector (org.fxyz.utils.FloatCollector)6 ArrayList (java.util.ArrayList)5 ObjectProperty (javafx.beans.property.ObjectProperty)5