Interpolation of 2D surface in 3D scene - JavaFX

时间:2016-10-09 15:59:00

标签: javafx java-8 javafx-8 surface

Working on some old project and would like to implement some futures for self-learning. Trying to figure out how can I do interpolation on my surface, need to eliminate "artifacts", it does not look greate with them. Already found some information about interpolation in JavaFX and they are 7 types of :

  • Linear
  • Discrete
  • Ease-in
  • Ease-out
  • Ease-both
  • Spline
  • Tangent

Was thinking between Linear and Tangent, but honestly i do not know how exactly it would be.

If it is going about Tangent interpolation, it has to be between frames ? Linear is one of the argument of the KeyValue Constructor.

That is how it looks atm with those artefacts and animation does not look "smooth".

2D Surface

That is the code responsible of creating surface and animation.

  package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        // 1D - We does not need that
//        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));

        Parent root = FXMLLoader.load(getClass().getResource("packet3D/Window3DSceneView.fxml"));

        primaryStage.setTitle("Animation 1D");
        primaryStage.setScene(new Scene(root, 1200, 800));
        primaryStage.show();
    }

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


package sample.packet3D;
import java.util.function.Function;

import org.fxyz.cameras.CameraTransformer;
import org.fxyz.shapes.primitives.SurfacePlotMesh;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.paint.Color;
import javafx.scene.shape.CullFace;
import javafx.scene.transform.Rotate;
import javafx.util.Duration;


public class Window3DBuilder{

    private Group group;
    private SurfacePlotMesh surface;
    private final CameraTransformer cameraTransformer;
    private final PerspectiveCamera perspectiveCamera;
    private PointLight light;
    private double time = 0 ;
    private double lambda = 1;
    private double k = (2 * Math.PI) / lambda;
    private final Rotate rotateX = new Rotate(180, Rotate.X_AXIS);
    private final Rotate rotateY = new Rotate(-90, Rotate.Y_AXIS);



    private Function<Double, Double> gaussFunctionR;


    public Window3DBuilder( Group group, PerspectiveCamera perspectiveCamera ) {
        this.group = group;
        this.perspectiveCamera = perspectiveCamera;
        cameraTransformer = new CameraTransformer();
    }

    public void createScene() {

        createSurface();

        group.getChildren().addAll( surface, cameraTransformer  );

        createCamera();

        createLight();
        update();
    }

    private void createCamera() {
        cameraTransformer.setTranslate(0, 0, 0);
        cameraTransformer.getChildren().addAll(perspectiveCamera);

        perspectiveCamera.setNearClip(0.1);
        perspectiveCamera.setFarClip(100000.0);
        perspectiveCamera.setTranslateX((group.getBoundsInLocal().getMaxX() + group.getBoundsInLocal().getMinX()) / 2d);
        perspectiveCamera.setTranslateY((group.getBoundsInLocal().getMaxY() + group.getBoundsInLocal().getMinY()) / 2d);
        double max = Math.max(group.getBoundsInLocal().getWidth(), group.getBoundsInLocal().getHeight());
        perspectiveCamera.setTranslateZ(-2 * max);
    }

    private void createLight() {
        light = new PointLight(Color.WHITE);
        cameraTransformer.getChildren().add(light);
        light.setTranslateX(perspectiveCamera.getTranslateX());
        light.setTranslateY(perspectiveCamera.getTranslateY());
        light.setTranslateZ(perspectiveCamera.getTranslateZ() / 10);
    }

    private void createSurface() {

        this.gaussFunctionR = x ->  1 / (Math.pow( ( 1 + Math.pow(4 * time, 2 )), (1/4)))
                * Math.exp(-(( 1 / Math.pow(1 + (4 * time), 2)) * Math.pow(x - (k * time), 2) ))
                * Math.cos((1/2) * Math.atan(-(2 * time)) + 1 / Math.pow(1 + (4 * time), 2)
                * ((k + (2 * time * x)) * x - Math.pow(1/2 * time * k, 2))) ;    

        surface = new SurfacePlotMesh(p ->  gaussFunctionR.apply(Math.sqrt(p.getY()*p.getY()+p.getX()*p.getX())) ,15, 15, 100, 100, 2);

        surface.setCullFace(CullFace.NONE);
        surface.setTextureModeVertices3D(1530, p -> p.magnitude());
        surface.getTransforms().addAll(rotateX, rotateY);
    }
    private void update() {


        Timeline timeLine = new Timeline();

        KeyFrame keyFrame = new KeyFrame(Duration.millis(50), e ->  {               
            surface.setFunction2D(p ->  gaussFunctionR.apply(Math.sqrt(p.getY()*p.getY()+p.getX()*p.getX())));                        
            increaseTime();   
        });
        timeLine.getKeyFrames().add(keyFrame);

        timeLine.setCycleCount(Timeline.INDEFINITE);
        timeLine.setAutoReverse(true);
        timeLine.play();
    }

    private void increaseTime(){
        this.time += 0.001;
    }


    public CameraTransformer getCameraTransformer() {
        return this.cameraTransformer;
    }

}


package sample.packet3D;


import org.fxyz.cameras.CameraTransformer;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.fxml.FXML;

import javafx.scene.Group;

import javafx.scene.PerspectiveCamera;

import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;

public class Window3DController {

    @FXML
    private AnchorPane anchorPane;
    @FXML
    private Group group;

    private Window3DBuilder window3dBuilder;
    private PerspectiveCamera perspectiveCamera;
    private CameraTransformer cameraTransformer;
    private double mousePosX;
    private double mousePosY;
    private double mouseOldX;
    private double mouseOldY;
    private double mouseDeltaX;
    private double mouseDeltaY;


    @FXML
    public void initialize() {
        perspectiveCamera = new PerspectiveCamera(true);

        window3dBuilder = new Window3DBuilder(group, perspectiveCamera);

        window3dBuilder.createScene();

        cameraTransformer = window3dBuilder.getCameraTransformer();

        group.sceneProperty().addListener(new InvalidationListener() {
            @Override
            public void invalidated(Observable observable) {
                group.getScene().setCamera(perspectiveCamera);
                group.sceneProperty().removeListener(this);
            }
        });

    }
    @FXML 
    public void onKeyPressed(KeyEvent event) {
              double change = 10.0;
              if(event.isShiftDown()) { change = 50.0; }
              KeyCode keycode = event.getCode();
              if(keycode == KeyCode.W) { perspectiveCamera.setTranslateZ(perspectiveCamera.getTranslateZ() + change); }
              if(keycode == KeyCode.S) { perspectiveCamera.setTranslateZ(perspectiveCamera.getTranslateZ() - change); }
              if(keycode == KeyCode.A) { perspectiveCamera.setTranslateX(perspectiveCamera.getTranslateX() - change); }
              if(keycode == KeyCode.D) { perspectiveCamera.setTranslateX(perspectiveCamera.getTranslateX() + change); } 


    }
    @FXML
    private void onMousePressed(MouseEvent me) {
             mousePosX = me.getSceneX();
             mousePosY = me.getSceneY();
             mouseOldX = me.getSceneX();
             mouseOldY = me.getSceneY();
    }
    @FXML
    private void onMouseDragged(MouseEvent me) {
            mouseOldX = mousePosX;
            mouseOldY = mousePosY;
            mousePosX = me.getSceneX();
            mousePosY = me.getSceneY();
            mouseDeltaX = (mousePosX - mouseOldX);
            mouseDeltaY = (mousePosY - mouseOldY);

            double modifier = 10.0;
            double modifierFactor = 0.1;

            if (me.isControlDown()) {
                modifier = 0.1;
            }
            if (me.isShiftDown()) {
                modifier = 50.0;
            }
            if (me.isPrimaryButtonDown()) {
                cameraTransformer.ry.setAngle(((cameraTransformer.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180);  // +
                cameraTransformer.rx.setAngle(((cameraTransformer.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180);  // -
            } else if (me.isSecondaryButtonDown()) {
                double z = perspectiveCamera.getTranslateZ();
                double newZ = z + mouseDeltaX * modifierFactor * modifier;
                perspectiveCamera.setTranslateZ(newZ);
            } else if (me.isMiddleButtonDown()) {
                cameraTransformer.t.setX(cameraTransformer.t.getX() + mouseDeltaX * modifierFactor * modifier * 0.3);  // -
                cameraTransformer.t.setY(cameraTransformer.t.getY() + mouseDeltaY * modifierFactor * modifier * 0.3);  // -
            }
    }

}

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.effect.*?>
<?import javafx.scene.canvas.*?>
<?import javafx.scene.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane fx:id="anchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onMouseDragged="#onMouseDragged" onMousePressed="#onMousePressed" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.packet3D.Window3DController">
   <children>
      <Group fx:id="group" onKeyPressed="#onKeyPressed">

      </Group>
   </children>
</AnchorPane>

0 个答案:

没有答案