skip to Main Content

In order to my lack of knowledge is it about how to create 3d model from 2d point(coordinates/paths) in java and showing on javafx?
in the basics I know how to use camera and light system and it’s not a problem but I have Picture from stone (Original Image) that User with mouse input selected points, The codes:

(The canvas put it on ImageView that have original Image. the canvas w , h bind to parent of imageView and imageview bind to parent w,h (so the imageview and canvas are the same w,h))

        canvas.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                if (isStarted()) {
                    App.logger.debug("Added the Point into: -> X: " + mouseEvent.getX() + " And Y: " + mouseEvent.getY());
                    points.add(new Point2D(mouseEvent.getX(), mouseEvent.getY()));
                    reDraw();
                    restorePoints = new ArrayList<Point2D>();
                } else {
                    App.logger.debug("The Start stat is :" + isStarted() + " So we can't Draw Shapes.");
                }
            }
        });

The points and restore point are : ArrayList<Point2D> points = new ArrayList<Point2D>() and I have correct point of image that show me the area selected to be 3d, but I can’t find how to change this into 3d model from 3dpoints (for z the user select z and I set all point z )

 ArrayList<Point3D> points3D = new ArrayList<Point3D>();
        for (Point2D point2D : points) {
            points3D.add(new Point3D(point2D.getX(), point2D.getY(), 24));
        }

in extra information I convert the points into Path with this code :

    private void connectJoint() {
        Point2D startPoint = null;
        Point2D startingPoint = null, endingPoint = null;
        Collection<PathElement> pathElements = new ArrayList<PathElement>();
        for (Point2D point : points) {
            if (startPoint == null) {
                startingPoint = point;
                startPoint = point;
                pathElements.add(new MoveTo(point.getX(), point.getY()));
                continue;
            }
            pathElements.add(new LineTo(point.getX(), point.getY()));
            graphicsContext.strokeLine(startPoint.getX(), startPoint.getY(), point.getX(), point.getY());
            pathElements.add(new LineTo(startingPoint.getX(), startingPoint.getY()));
            startPoint = point;
        }
        endingPoint = startPoint;
        if (startingPoint != null && endingPoint != null && points.size() > 2) {
            shadowLastLine(startingPoint, endingPoint);

        }
        pathOfSelectedAreaWithEndJoined = new Path(pathElements);
    }

So, back in My Question: How I can create 3dModel from the points or path I have in java to show in javafx?

enter image description here

For Update My Question, Created the 3D model with Photoshop that show what actually I’m looking for :
enter image description here
I have Point3D that is from Point2D and ill create 2 ArrayList from it one for top layout and other for bottom layout some of them with z=0 and the other z=(Anything user selected). But what’s really Idk is How to show this! in some point Using extra library or TrianglMesh can’t show it and it’s make so many convert the code for showing something like that!

2

Answers


  1. This approach will mesh MeshView object with xy parent’s coordinates ( z is alway 0 ) given by PickResult. There are some issues about topology and artifacts .
    Since a tringle has 9 coordinates (3 vertices ) the condition will start at third click event . And , every new click needs a new face after the first triangle . That is why faces array needs to be cleared with mesh.getFaces().clear() method.

    All 3d vertices are pointing to u =0 & v=0 uv coordinates and raster images can not be applied as texture . Check this answer

    meshview javafx

    App.java

    public class App extends Application {
    
        private final TriangleMesh mesh = new TriangleMesh();
    
        @Override
        public void start(Stage stage) {
    
            mesh.getTexCoords().addAll(0, 0);
            MeshView meshView = new MeshView(mesh);
            meshView.setMaterial(new PhongMaterial(Color.CYAN));
    
            AnchorPane anchorPane = new AnchorPane(meshView);
    
            anchorPane.setOnMouseClicked(e -> {
                float x = (float) e.getX();
                float y = (float) e.getY();
    
                mesh.getPoints().addAll(x, y, 0);
    
                if (mesh.getPoints().size() >= 9) {
    
                    makeFaces();
                }
    
            });
    
            var scene = new Scene(anchorPane, 640, 480);
            stage.setScene(scene);
            stage.show();
        }
    
        private void makeFaces() {
            mesh.getFaces().clear();
            int vertices = mesh.getPoints().size();
            int faces = 1 + ((vertices - 9) / 3);
    
            for (int i = 0; i < faces; i++) {
    
                mesh.getFaces().addAll(i, 0, i + 1, 0, i + 2, 0);
    
            }
    
        }
    
        public static void main(String[] args) {
            launch();
        }
    
    }
    
    Login or Signup to reply.
  2. Meshing a MeshView object from 2d coordinates

    meshview javafx

    There is an array of Point2d wich are replaced by a custom class that extends Rectangle to visulize where we can click . We need to click three different dots(Rectangles) to thrigger this sequence :

    1. check if the dot x&y coords already exists in points array from the TriangleMesh instance . If is not it will add it.

    2. check its vertex index with searchByCoords method

    3. Once 1 and 2 steps were done for all 3 dots . It will add a new face for faces array in the mesh instance .

    4. It will clear the array were those 3 clicked dots were stored allowing next iterations.

    All uv coordinates are the same (0,0) and raster images can not be applied as textures . Check this answer

    javafx does not support ngons

    This is a single class javafx app you can try

    App.java

    public class App extends Application {
    
        private Point2D[] points;
    
        private ArrayList<Dot> clickedDots = new ArrayList<>();
    
        private final ArrayList<Dot> dots = new ArrayList<>();
    
        private final AnchorPane anchorPane = new AnchorPane();
    
        private final TriangleMesh mesh = new TriangleMesh(VertexFormat.POINT_TEXCOORD);
    
        @Override
        public void start(Stage stage) {
    
            MeshView meshView = new MeshView(mesh);
            meshView.setMaterial(new PhongMaterial(Color.YELLOWGREEN));
            mesh.getTexCoords().addAll(0, 0);
            meshView.setDisable(true);
    
            Button drawmode = new Button("mode");
            drawmode.setOnAction(e -> {
                if (meshView.getDrawMode() == DrawMode.FILL) {
                    meshView.setDrawMode(DrawMode.LINE);
                } else {
                    meshView.setDrawMode(DrawMode.FILL);
                }
    
            });
            AnchorPane.setRightAnchor(drawmode, 5d);
            anchorPane.getChildren().add(drawmode);
            Button reset = new Button("reset");
            reset.setOnAction(e -> {
    
                mesh.getFaces().clear();
                mesh.getPoints().clear();
                clickedDots.forEach(dot -> {
                    dot.clear();
                });
                clickedDots.clear();
    
            });
            AnchorPane.setRightAnchor(reset, 60d);
            anchorPane.getChildren().add(reset);
    
            points = new Point2D[]{new Point2D(10, 10), new Point2D(100, 10),
                new Point2D(150, 10), new Point2D(160, 20), new Point2D(180, 25),
                new Point2D(180, 200), new Point2D(160, 200), new Point2D(100, 200), new Point2D(10, 200)};
    
            populate();
            anchorPane.getChildren().add(meshView);
    
            anchorPane.setOnMouseClicked(e -> {
    
                if (e.getPickResult().getIntersectedNode() instanceof Dot) {
                    Dot dot = (Dot) e.getPickResult().getIntersectedNode();
    
                    if (!dot.isSelected) {
                        dot.select();
                        clickedDots.add(dot);
                    }
                }
                if (clickedDots.size() == 3) {
                    float z = 0;
                    // vertex1
                    float x1 = (float) clickedDots.get(0).getTranslateX();
                    float y1 = (float) clickedDots.get(0).getTranslateY();
    
                    if (!wasXYAdded(x1, y1)) {
                        mesh.getPoints().addAll(x1, y1, z);
                    }
                    int vertext1 = searchByCoords(x1, y1);
              
                    
                    // vertex2
                    float x2 = (float) clickedDots.get(1).getTranslateX();
                    float y2 = (float) clickedDots.get(1).getTranslateY();
    
                    if (!wasXYAdded(x2, y2)) {
                        mesh.getPoints().addAll(x2, y2, z);
                    }
                    int vertext2 = searchByCoords(x2, y2);
                   
    
                    // vertex3
                    float x3 = (float) clickedDots.get(2).getTranslateX();
                    float y3 = (float) clickedDots.get(2).getTranslateY();
    
                    if (!wasXYAdded(x3, y3)) {
                        mesh.getPoints().addAll(x3, y3, z);
                    }
                    int vertext3 = searchByCoords(x3, y3);
                  
    
                    mesh.getFaces().addAll(vertext1, 0, vertext2, 0, vertext3, 0);
                    mesh.getFaces().addAll(vertext3, 0, vertext2, 0, vertext1, 0);
    
                    clickedDots.forEach(dot -> {
                        dot.clear();
    
                    });
                    clickedDots.clear();
                }
    
            });
    
            var scene = new Scene(anchorPane, 320, 300);
            stage.setScene(scene);
            stage.setTitle("meshing from 2d coords");
            stage.show();
    
        }
    
        private int searchByCoords(float x, float y) {
            for (int i = 0; i < mesh.getPoints().size() / 3; i++) {
    
                float testX = mesh.getPoints().get(i * 3);
                float testY = mesh.getPoints().get((i * 3) + 1);
                if (testX == x && testY == y) {
                    return i;
                }
    
            }
            return ((mesh.getPoints().size() / 3));
        }
    
        private boolean wasXYAdded(float x, float y) {
            for (int i = 0; i < mesh.getPoints().size() / 3; i++) {
    
                float testX = mesh.getPoints().get(i * 3);
                float testY = mesh.getPoints().get((i * 3) + 1);
                if (testX == x && testY == y) {
                    
                    return true;
                }
    
            }
            return false;
        }
    
        public static void main(String[] args) {
            launch();
        }
    
        private void populate() {
    
            for (Point2D point : points) {
    
                Dot dot = new Dot(point.getX(), point.getY());
                dots.add(dot);
                anchorPane.getChildren().add(dot);
    
            }
    
        }
    
        private class Dot extends Rectangle {
    
            private boolean isSelected = false;
    
            public Dot(double x, double y) {
                setTranslateX(x);
                setTranslateY(y);
                setWidth(10);
                setHeight(10);
                setFill(Color.BLACK);
    
            }
    
            public void clear() {
                setFill(Color.BLACK);
                isSelected = false;
            }
    
            public void select() {
                setFill(Color.ORANGERED);
                isSelected = true;
            }
        }
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search