JavaFX Making Earth Spin with Controls, Simulation 3D Tutorial, Full Source Code

java

Talking about Earth, nothing but Sphere here, in this tutorial we will learn on how to simulate earth with it’s material details with Bump Map. First thing you need to know about Bump mapping concept. Bumps Map allows us to add some extra details to object.

Bump mapping is the texture mapping technique in computer graphics for simulating bumps and wrinkles on the surface of an object.

Using JavaFX we will simulate the Earth that rotates with effects like (Lighting, Reflection and Bumps) and adding some controls. You can downloads images from

https://www.google.com/search?q=earth+diffuse+map&tbm=isch&ved=2ahUKEwit3sbxzYv2AhVatqQKHe7XAKEQ2-cCegQIABAA which is I used in this tutorial.

After downloading the images put them into folder called ‘resources’ as I used for this tutorial or else name you wish but remember to call it.

Here are the JavaFX source code

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package earth;

import com.jfoenix.controls.JFXSlider;
import com.jfoenix.controls.JFXSlider.IndicatorPosition;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

/**
 *
 * @author ponsi
 */
public class Earth extends Application {

    private static final float WIDTH = 1000;
    private static final float HEIGHT = 700;

    private double anchorX, anchorY;
    private double anchorAngleX = 0;
    private double anchorAngleY = 0;
    private final DoubleProperty angleX = new SimpleDoubleProperty(0);
    private final DoubleProperty angleY = new SimpleDoubleProperty(0);
    private final Sphere sphere = new Sphere(150);

    @Override
    public void start(Stage primaryStage) {

        Camera camera = new PerspectiveCamera(true);
        camera.setNearClip(1);
        camera.setFarClip(10000);
        camera.translateZProperty().set(-1000);

        SmartGroup world = new SmartGroup();
        world.getChildren().add(prepareEarth());

        Slider slider = prepareSlider();
        world.translateZProperty().bind(slider.valueProperty());

        Group root = new Group();
        root.getChildren().add(world);
        root.getChildren().add(prepareImageView());
        root.getChildren().add(slider);

        Scene scene = new Scene(root, WIDTH, HEIGHT, true);
        scene.setFill(Color.SILVER);
        scene.setCamera(camera);

        initMouseControl(world, scene, primaryStage);

        primaryStage.setTitle("PONCE GK");
        primaryStage.setScene(scene);
        primaryStage.show();

        prepareAnimation();

    }

    private void prepareAnimation() {
        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                sphere.rotateProperty().set(sphere.getRotate() + 0.2);
            }

        };
        timer.start();
    }

    private ImageView prepareImageView() {
        Image image = new Image(Earth.class.getResourceAsStream("/resources/earth/galaxy.jpg"));
        ImageView imageView = new ImageView(image);
        imageView.setPreserveRatio(true);
        imageView.getTransforms().add(new Translate(-image.getWidth() / 2, -image.getHeight() / 2, 700));

        return imageView;
    }

    private Slider prepareSlider() {
        JFXSlider slider = new JFXSlider();
        slider.setPrefWidth(400d);
        slider.setIndicatorPosition(IndicatorPosition.RIGHT);

        slider.setMax(800);
        slider.setMin(-400);
        slider.setLayoutX(-170);
        slider.setLayoutY(210);
        slider.setTranslateZ(5);


        return slider;
    }

    private Node prepareEarth() {
        PhongMaterial earthMaterial = new PhongMaterial();
        earthMaterial.setDiffuseMap(new Image(getClass().getResourceAsStream("/resources/earth/earth-d.jpg")));
        earthMaterial.setSelfIlluminationMap(new Image(getClass().getResourceAsStream("/resources/earth/earth-l.jpg")));
        earthMaterial.setSpecularMap(new Image(getClass().getResourceAsStream("/resources/earth/earth-s.jpg")));
        earthMaterial.setBumpMap(new Image(getClass().getResourceAsStream("/resources/earth/earth-n.jpg")));

        sphere.setMaterial(earthMaterial);
        sphere.setRotationAxis(Rotate.Y_AXIS);
        return sphere;
    }

    private void initMouseControl(SmartGroup group, Scene scene, Stage stage) {
        Rotate xRotate;
        Rotate yRotate;

        group.getTransforms().addAll(
                xRotate = new Rotate(0, Rotate.X_AXIS),
                yRotate = new Rotate(0, Rotate.Y_AXIS)
        );
        xRotate.angleProperty().bind(angleX);
        yRotate.angleProperty().bind(angleY);

        scene.setOnMousePressed(event -> {
            anchorX = event.getSceneX();
            anchorY = event.getSceneY();
            anchorAngleX = angleX.get();
            anchorAngleY = angleY.get();
        });

        scene.setOnMouseDragged(event -> {
            angleX.set(anchorAngleX - (anchorY - event.getSceneY()));
            angleY.set(anchorAngleY + anchorX - event.getSceneX());
        });

        stage.addEventHandler(ScrollEvent.SCROLL, event -> {
            double delta = event.getDeltaY();
            group.translateZProperty().set(group.getTranslateZ() + delta);
        });

    }

    class SmartGroup extends Group {

        Rotate r;
        Transform t = new Rotate();

        void roatateByX(int ang) {
            r = new Rotate(ang, Rotate.X_AXIS);
            t = t.createConcatenation(r);
            this.getTransforms().clear();
            this.getTransforms().addAll(t);
        }

        void roatateByY(int ang) {
            r = new Rotate(ang, Rotate.Y_AXIS);
            t = t.createConcatenation(r);
            this.getTransforms().clear();
            this.getTransforms().addAll(t);
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

NB:

You need to include jfoenix jar file library in your project.


Other Recommended for you

  • .How to Generate Line Chart Using JavaFX
  • .How to Generate Bar Chart Using JavaFx