使用三角形网格纹理而无需读/写图像文件

时间:2014-11-12 07:57:21

标签: javafx textures texture-mapping

这是对上一个问题的跟进(见Coloring individual triangles in a triangle mesh on javafx),我认为这是另一个话题。

有没有办法(使用javafx)我可以远离实际写入磁盘(或外部设备)的图像文件以使用纹理?

换句话说:我可以使用特定的纹理而不必使用Image吗?

由于我的色彩映射会在运行时发生变化,因此我不希望每次运行时都要写入磁盘。此外,对于使用我的应用程序的人来说,这可能是一个安全问题(写入磁盘)。(使用javafx)

2 个答案:

答案 0 :(得分:3)

您可以使用任何图形对象在代码中创建用于填充等的纹理,并将其转换为内存中的图像,而不是触摸磁盘。

下面的示例将使用绿色样条线创建纹理。

Pane testImage2(Pane pane) {
    Pane inner = new Pane();
    inner.prefWidthProperty().bind(pane.widthProperty());
    inner.prefHeightProperty().bind(pane.heightProperty());
    pane.getChildren().add(inner);

    SVGPath texture = new SVGPath();
    texture.setStroke(Color.GREEN);
    texture.setStrokeWidth(2.5);
    texture.setFill(Color.TRANSPARENT);
    texture.setContent("M 10 10 C 40 10 10 70 70 20");

    SnapshotParameters params = new SnapshotParameters();
    params.setViewport(new Rectangle2D(-5, -5, 70, 50));
    Image image = texture.snapshot(params, null);

    Paint paint = new ImagePattern(image, 5,5, 20, 20, false);
    inner.setBackground(new Background(new BackgroundFill(paint, new CornerRadii(0), new Insets(inset))));
    return pane;
}

enter image description here

答案 1 :(得分:2)

正如@ Jens-Peter-Haack建议的那样,使用Snapshot,您可以创建任何所需的图像,然后将此图像应用为扩散图。为此,您需要创建一些节点,用您需要的颜色填充它们,将它们分组到一个容器中,然后拍摄快照。

有一种直接的方法,你可以使用PixelWriter建立一个带有颜色图案的图像。

假设你想要256种颜色,这种方法将返回256像素的图像,其中每个像素都有这些颜色中的一种。为简单起见,我添加了两种构建调色板的简单方法。

public static Image colorPallete(int numColors){
    int width=(int)Math.sqrt(numColors);
    int height=numColors/width;

    WritableImage img = new WritableImage(width, height);
    PixelWriter   pw  = img.getPixelWriter();
    AtomicInteger count = new AtomicInteger();
    IntStream.range(0, height).boxed()
            .forEach(y->IntStream.range(0, width).boxed()
                    .forEach(x->pw.setColor(x, y, getColor(count.getAndIncrement(),numColors))));

    // save for testing purposes
    try {            
        ImageIO.write(SwingFXUtils.fromFXImage(img, null), "jpg", new File("palette.jpg"));
    } catch (IOException ex) { }
    return img;
}

private Color getColor(int iColor, int numColors){
    // nice palette of colors 
    java.awt.Color c = java.awt.Color.getHSBColor((float) iColor / (float) numColors, 1.0f, 1.0f);
    return Color.rgb(c.getRed(), c.getGreen(), c.getBlue());

    // raw palette
    //return Color.rgb((iColor >> 16) & 0xFF, (iColor >> 8) & 0xFF, iColor & 0xFF);
}

获得图像对象后,可以设置漫反射贴图:

IcosahedronMesh mesh = new IcosahedronMesh();
PhongMaterial mat = new PhongMaterial();
mat.setDiffuseMap(colorPallete(256));
mesh.setMaterial(mat);

但是你仍然需要为新纹理提供正确的映射。

为此,您需要将网格的顶点映射到图像中的像素。

首先,我们需要一种在网格上用纹理坐标映射颜色的方法。此方法将返回给定颜色索引的一对坐标:

public static float[] getTextureLocation(int iPoint, int numColors){
    int width=(int)Math.sqrt(numColors);
    int height=numColors/width;
    int y = iPoint/width; 
    int x = iPoint-width*y;
    return new float[]{(((float)x)/((float)width)),(((float)y)/((float)height))};
}

最后,我们将这些纹理添加到m.getTextCoords()和面m.getFaces(),如图here所示。

如果我们为二十面体中的每个顶点指定一种颜色,我们从所有调色板中选择一种颜色(根据颜色和顶点的数量向上或向下缩放),然后用t0 = p0,t1 = p1设置每个面, T2 = P2:

IntStream.range(0,numVertices).boxed()
    .forEach(i->m.getTexCoords()
                 .addAll(getTextureLocation(i*numColors/numVertices,numColors)));

m.getFaces().addAll(
            1, 1, 11, 11, 7, 7, 
            1, 1, 7, 7, 6, 6, 
            1, 1, 6, 6, 10, 10, 
            1, 1, 10, 10, 3, 3, 
            1, 1, 3, 3, 11, 11,
            4, 4, 8, 8, 0, 0, 
            5, 5, 4, 4, 0, 0, 
            9, 9, 5, 5, 0, 0, 
            2, 2, 9, 9, 0, 0, 
            8, 8, 2, 2, 0, 0,
            11, 11, 9, 9, 7, 7,
            7, 7, 2, 2, 6, 6, 
            6, 6, 8, 8, 10, 10, 
            10, 10, 4, 4, 3, 3, 
            3, 3, 5, 5, 11, 11,
            4, 4, 10, 10, 8, 8, 
            5, 5, 3, 3, 4, 4, 
            9, 9, 11, 11, 5, 5, 
            2, 2, 7, 7, 9, 9, 
            8, 8, 6, 6, 2, 2
    );

这会给我们这样的事情:

enter image description here

修改

使用纹理坐标,而不是使用颜色映射节点,您可以添加一些功能并轻松创建等高线图,如下所示:

enter image description here