Как сделать концы Cylinder прозрачными в JavaFX - PullRequest
3 голосов
/ 03 октября 2019

В настоящее время я пытаюсь сделать концы цилиндра полностью прозрачными, сохраняя при этом стороны материала. Я не уверен, как этого добиться. Эта тема упоминает об этом, но все ссылки не работают

Я думаю, что мне нужно использовать плоскость отсечения? Хотя я не знаю, с чего начать.

Вот что я сейчас использую, чтобы просто установить полупрозрачный материал!

        Cylinder line = new Cylinder(getRadius()/4, height);
        lineMaterial = new PhongMaterial();
        lineMaterial.setDiffuseColor(new Color(1,1,1,0.5));
        lineMaterial.diffuseMapProperty();
        line.setMaterial(lineMaterial);

1 Ответ

3 голосов
/ 04 октября 2019

Один из возможных способов получить прозрачность - использовать png в качестве рассеянного изображения с несколькими прозрачными пикселями.

Хотя это работает, если вы примените поверх встроенного JavaFX Cylinder, вы выиграете 'получить ожидаемый результат, потому что цилиндр применяет одно и то же изображение к и вертикальной трубе и двум поверхностям крышки. Так что это не сработает для вашего случая.

Может быть возможность удалить колпачки из сетки цилиндра и получить только трубку , но, к сожалению, она не экспортирует свой треугольникmesh.

Пока что лучшим вариантом является создание непосредственно сетки трубки, и для этого мы можем повторно использовать сетку цилиндра, проверив открытый исходный код в (новом) OpenJDK/ JFX GitHub репозиторий.

Следующий метод создает TriangleMesh трубки высотой h, радиус r, с делениями div (производя 2 * div треугольников). Это тот же код, что и в Cylinder, но без точек шапки, координат текстур и массивов граней.

private static TriangleMesh createMesh(int div, float h, float r) {

    final int nPoints = div * 2;
    final int tcCount = (div + 1) * 2;
    final int faceCount = div * 2;

    float textureDelta = 1.f / 256;

    float dA = 1.f / div;
    h *= .5f;

    float points[] = new float[nPoints * 3];
    float tPoints[] = new float[tcCount * 2];
    int faces[] = new int[faceCount * 6];
    int smoothing[] = new int[faceCount];

    int pPos = 0, tPos = 0;

    for (int i = 0; i < div; ++i) {
        double a = dA * i * 2 * Math.PI;
        points[pPos + 0] = (float) (Math.sin(a) * r);
        points[pPos + 1] = h;
        points[pPos + 2] = (float) (Math.cos(a) * r);
        tPoints[tPos + 0] = 1 - dA * i;
        tPoints[tPos + 1] = 1 - textureDelta;
        pPos += 3; tPos += 2;
    }

    // top edge
    tPoints[tPos + 0] = 0;
    tPoints[tPos + 1] = 1 - textureDelta;
    tPos += 2;

    for (int i = 0; i < div; ++i) {
        double a = dA * i * 2 * Math.PI;
        points[pPos + 0] = (float) (Math.sin(a) * r);
        points[pPos + 1] = -h;
        points[pPos + 2] = (float) (Math.cos(a) * r);
        tPoints[tPos + 0] = 1 - dA * i;
        tPoints[tPos + 1] = textureDelta;
        pPos += 3; tPos += 2;
    }

    // bottom edge
    tPoints[tPos + 0] = 0;
    tPoints[tPos + 1] = textureDelta;
    tPos += 2;

    int fIndex = 0;

    // build body faces
    for (int p0 = 0; p0 < div; ++p0) {
        int p1 = p0 + 1;
        int p2 = p0 + div;
        int p3 = p1 + div;

        // add p0, p1, p2
        faces[fIndex+0] = p0;
        faces[fIndex+1] = p0;
        faces[fIndex+2] = p2;
        faces[fIndex+3] = p2 + 1;
        faces[fIndex+4] = p1 == div ? 0 : p1;
        faces[fIndex+5] = p1;
        fIndex += 6;

        // add p3, p2, p1
        faces[fIndex+0] = p3 % div == 0 ? p3 - div : p3;
        faces[fIndex+1] = p3 + 1;
        faces[fIndex+2] = p1 == div ? 0 : p1;
        faces[fIndex+3] = p1;
        faces[fIndex+4] = p2;
        faces[fIndex+5] = p2 + 1;
        fIndex += 6;

    }

    for (int i = 0; i < div * 2; ++i) {
        smoothing[i] = 1;
    }

    TriangleMesh m = new TriangleMesh();
    m.getPoints().setAll(points);
    m.getTexCoords().setAll(tPoints);
    m.getFaces().setAll(faces);
    m.getFaceSmoothingGroups().setAll(smoothing);
    return m;
}

Теперь вам нужно будет создать MeshView, чтобы вы могли добавить егок вашей сцене:

private static MeshView createTube(int div, float h, float r) {
    MeshView meshView = new MeshView(createMesh(div, h, r));
//        meshView.setDrawMode(DrawMode.LINE);
    meshView.setCullFace(CullFace.NONE);
    PhongMaterial material = new PhongMaterial(Color.RED);
    meshView.setMaterial(material);
    return meshView;
}

Создайте и добавьте один к своей сцене:

MeshView tube = createTube(64, 5f, 1.6f);
Scene scene = new Scene(new Group(tube), 600, 600, true, SceneAntialiasing.BALANCED);

И вы получите свою трубку:

Tube

Вы также можете применить диффузное изображение в качестве текстуры:

material.setDiffuseMap(new Image(getClass.getResourceAsStream("440px-JavaFX_Logo.png")));

Texture

...