'Painting difuse texture in javafx?

Is there a way to paint a 3d texture on a 3d surface like blender ?



Solution 1:[1]

Painting a texture in 3d scene

painting javafx 3d texture

getPickResult().getIntersectedTexCoord() from mouseEvent will return a point2d wich is an uv coordinate (from 0 to 1 ). In order to map it to the image pixels ; we have to multilpy u & v by image height and width (800 in this case). Once we have pixel coordinates we can paint with pixelWriter.setPixels() method . the third and fourth arguments in setPixel corresponding to the rectangle that is used to draw , in this case is a 12*12 square . Therefore , an argb array 144 length is needed to fill the square in setPixels with color values given by colorpicker result . ImageView and DifuseMap share the same WritableImage that is why painting the Shape3d will update image in imageView as well

This is a single class javafx functional app you can try . you can rotate with right mouse button and painting with left button

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;
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Giovanni Contreras