在 javafx 中绘制漫反射纹理?

Painting difuse texture in javafx?

有没有办法像 blender 那样在 3d 表面上绘制 3d 纹理?

在 3d 场景中绘制纹理

来自 mouseEvent 的

getPickResult().getIntersectedTexCoord() 将 return point2d 是一个 uv 坐标(从 0 到 1 )。为了将它映射到图像像素;我们必须将 u & v 乘以图像的高度和宽度(在本例中为 800)。一旦我们有了像素坐标,我们就可以使用 pixelWriter.setPixels() 方法进行绘制。 setPixel 中的第三个和第四个参数对应于用于绘制的矩形,在本例中是一个 12*12 的正方形。因此,需要一个长度为 144 的 argb 数组来用 colorpicker 结果给出的颜色值填充 setPixels 中的正方形。 ImageView 和 DifuseMap 共享相同的 WritableImage,这就是为什么绘制 Shape3d 也会更新 imageView 中的图像

这是一个您可以尝试的 class javafx 功能应用程序。你可以用鼠标右键旋转和左键绘画

public class App extends Application {

    private boolean paintMode;
    private boolean rotaionMode;
    private double anchorX;
    private final WritableImage writableImage = new WritableImage(800, 800);
    private int[] colorArray;

    private PixelWriter pixelWriter = writableImage.getPixelWriter();

    @Override
    public void start(Stage stage) {

        // this loop will paint all writableImage object pixel with Color.WHEAT
        for (int i = 0; i < 800; i++) {

            for (int j = 0; j < 800; j++) {
                pixelWriter.setColor(i, j, Color.WHEAT);

            }
        }
        //  giving a starting value to colorPicker
        ColorPicker picker = new ColorPicker(Color.AQUAMARINE);

        // giving initial valuest to colorArray
        colorArray = getColorArray(picker.getValue());

        picker.setOnAction(e -> colorArray = getColorArray(picker.getValue()));

        PerspectiveCamera camera = new PerspectiveCamera(true);
        camera.setTranslateZ(-30);
        Shape3D sphere = new Sphere(6);
        PhongMaterial material = new PhongMaterial();
        material.setDiffuseMap(writableImage);
        material.setDiffuseColor(Color.CORAL);
        sphere.setMaterial(material);

        sphere.setOnMousePressed(e -> {
            if (e.isSecondaryButtonDown()) {
                anchorX = e.getSceneX();

            }
            rotaionMode = e.isSecondaryButtonDown();
            paintMode = e.isPrimaryButtonDown();

        });

        sphere.setOnMouseDragged(e -> {
            // painting if primary button is pressed 
            Point2D intersectedTexCoord = e.getPickResult().getIntersectedTexCoord();
            if (paintMode && intersectedTexCoord != null) {
                // uv cordinates to writableImage x y indices 
                int x = (int) (intersectedTexCoord.getX() * 800);
                int y = (int) (intersectedTexCoord.getY() * 800);

                // the rectangle of pixelWritter is 12*12 therefore an array 144 length of argb is needed 
                pixelWriter.setPixels(x, y, 12, 12, PixelFormat.getIntArgbInstance(), colorArray, 0, 0);

            }
            // rotate if secondary button is pressred
            if (rotaionMode) {

                sphere.setRotationAxis(Rotate.Y_AXIS);

                sphere.setRotate(sphere.getRotate() + (e.getSceneX() - anchorX) * -0.05);

            }

        });

        // writableImage in imageView and difuseMap 
        ImageView imageView = new ImageView(writableImage);
        imageView.setFitHeight(300);
        imageView.setFitWidth(300);

        Group group = new Group(camera, sphere);
        SubScene subScene = new SubScene(group, 300, 300, true, SceneAntialiasing.BALANCED);
        subScene.setFill(Color.AQUAMARINE);
        subScene.setCamera(camera);
        HBox hBox = new HBox(picker, subScene, imageView);
        hBox.setAlignment(Pos.CENTER);
        hBox.setSpacing(30);
        Scene scene = new Scene(hBox, 800, 600);
        stage.setTitle("painting 3d texture");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

    public int[] getColorArray(Color color) {
        // get color values in doubles
        double alphaD = color.getOpacity();
        double redD = color.getRed();
        double greenD = color.getGreen();
        double blueD = color.getBlue();

        // double to int
        int alpha = (int) Math.round(255 * alphaD);
        int red = (int) Math.round(255 * redD);
        int green = (int) Math.round(255 * greenD);
        int blue = (int) Math.round(255 * blueD);

        // shifting int on hex
        alpha = (alpha << 24) & 0xFF000000;
        red = (red << 16) & 0x00FF0000;
        green = (green << 8) & 0x0000FF00;
        blue = blue & 0x000000FF;

        // argb value
        int argb = alpha | red | green | blue;

        // the rectangle of pixelWritter is 12*12 therefore an array 144 length of argb is needed 
        int[] colors = new int[144];

        for (int i = 0; i < colors.length; i++) {

            colors[i] = argb;

        }

        return colors;
    }
}