package jp.yucchi.try3d;
import com.interactivemesh.jfx.importer.ImportException;
import com.interactivemesh.jfx.importer.obj.ObjModelImporter;
import java.net.URL;
import javafx.application.Application;
import javafx.beans.binding.When;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.scene.AmbientLight;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Background;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
public class Try3D extends Application {
private final DoubleProperty xPos = new SimpleDoubleProperty(0);
private final DoubleProperty yPos = new SimpleDoubleProperty(0);
private final DoubleProperty zPos = new SimpleDoubleProperty(0);
private final DoubleProperty sxPos = new SimpleDoubleProperty(1.0);
private final DoubleProperty syPos = new SimpleDoubleProperty(1.0);
private final DoubleProperty szPos = new SimpleDoubleProperty(1.0);
private final DoubleProperty rxPos = new SimpleDoubleProperty(0);
private final DoubleProperty ryPos = new SimpleDoubleProperty(0);
private final DoubleProperty rzPos = new SimpleDoubleProperty(0);
private final BooleanProperty showWireframe = new SimpleBooleanProperty(false);
private double anchorAngleX = 0;
private double anchorAngleY = 0;
private final DoubleProperty angleX = new SimpleDoubleProperty(0);
private final DoubleProperty angleY = new SimpleDoubleProperty(0);
private double anchorX;
private double anchorY;
private MeshView[] objMesh;
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Label translateLabel = new Label("Translate");
Label xLabel = new Label("X");
Label yLabel = new Label("Y");
Label zLabel = new Label("Z");
Label scaleLabel = new Label("Scale ");
Label sxLabel = new Label("X");
Label syLabel = new Label("Y");
Label szLabel = new Label("Z");
Label rotateLabel = new Label("Rotate ");
Label rxLabel = new Label("X");
Label ryLabel = new Label("Y");
Label rzLabel = new Label("Z");
Label drawModeLabel = new Label("Wireframe");
Label resetLabel = new Label(" Reset");
Slider xSlider = new Slider(-3000, 3000, 0);
Slider ySlider = new Slider(-3000, 3000, 0);
Slider zSlider = new Slider(-5000, 5000, 0);
Slider sxSlider = new Slider(0.01, 10, 1.0);
Slider sySlider = new Slider(0.01, 10, 1.0);
Slider szSlider = new Slider(0.01, 10, 1.0);
Slider rxSlider = new Slider(-360, 360, 0);
Slider rySlider = new Slider(-360, 360, 0);
Slider rzSlider = new Slider(-360, 360, 0);
xSlider.setPrefSize(533, 0);
ySlider.setPrefSize(533, 0);
zSlider.setPrefSize(533, 0);
sxSlider.setPrefSize(533, 0);
sySlider.setPrefSize(533, 0);
szSlider.setPrefSize(533, 0);
rxSlider.setPrefSize(533, 0);
rySlider.setPrefSize(533, 0);
rzSlider.setPrefSize(533, 0);
xSlider.setShowTickLabels(true);
xSlider.setMajorTickUnit(500);
ySlider.setShowTickLabels(true);
ySlider.setMajorTickUnit(500);
zSlider.setShowTickLabels(true);
zSlider.setMajorTickUnit(500);
sxSlider.setShowTickLabels(true);
sxSlider.setMajorTickUnit(2.0);
sySlider.setShowTickLabels(true);
sySlider.setMajorTickUnit(2.0);
szSlider.setShowTickLabels(true);
szSlider.setMajorTickUnit(2.0);
rxSlider.setShowTickLabels(true);
rxSlider.setMajorTickUnit(90);
rySlider.setShowTickLabels(true);
rySlider.setMajorTickUnit(90);
rzSlider.setShowTickLabels(true);
rzSlider.setMajorTickUnit(90);
CheckBox meshCheckBox = new CheckBox("Wireframe");
Button btn = new Button();
btn.setText("Reset");
final Accordion accordion = new Accordion();
final TitledPane translatePane = new TitledPane("Camera Translate", new HBox(30, translateLabel, xLabel, xSlider, yLabel, ySlider, zLabel, zSlider));
final TitledPane scalePane = new TitledPane("Camera Scale", new HBox(30, scaleLabel, sxLabel, sxSlider, syLabel, sySlider, szLabel, szSlider));
final TitledPane rotatePane = new TitledPane("Camera Rotate", new HBox(30, rotateLabel, rxLabel, rxSlider, ryLabel, rySlider, rzLabel, rzSlider));
final TitledPane drawModePane = new TitledPane("DrawMode & Reset", new HBox(20, drawModeLabel, meshCheckBox, resetLabel, btn));
translatePane.setAnimated(true);
scalePane.setAnimated(true);
rotatePane.setAnimated(true);
drawModePane.setAnimated(true);
accordion.getPanes().addAll(translatePane, scalePane, rotatePane, drawModePane);
accordion.setExpandedPane(translatePane);
root.getChildren().add(accordion);
accordion.setLayoutX(17);
accordion.setLayoutY(873);
Scene scene = new Scene(root, 1910, 1020, true);
scene.setFill(Color.PINK);
PerspectiveCamera cam = new PerspectiveCamera(false);
scene.setCamera(cam);
root.getChildren().add(cam);
// Create SubScene
PerspectiveCamera subCam = new PerspectiveCamera(false);
AnchorPane subRoot = new AnchorPane();
subRoot.setBackground(Background.EMPTY);
ObjModelImporter objImporter = new ObjModelImporter();
try {
URL objUrl = this.getClass().getResource("bunny/b.obj");
objImporter.read(objUrl);
} catch (ImportException e) {
e.printStackTrace();
return;
}
MeshView[] objMesh = objImporter.getImport();
objImporter.close();
Group objGroup = new Group();
for (int i = 0; i < objMesh.length; i++) {
objGroup.getChildren().addAll(objMesh[i]);
objMesh[i].drawModeProperty().bind(new When(showWireframe).then(DrawMode.LINE).otherwise(DrawMode.FILL));
}
objGroup.setLayoutX(960);
objGroup.setLayoutY(430);
AmbientLight ambient = new AmbientLight();
ambient.setColor(Color.rgb(255, 255, 255, 0.6));
PointLight point = new PointLight();
point.setColor(Color.rgb(255, 255, 255, 1.0));
point.setLayoutX(400);
point.setLayoutY(100);
point.setTranslateZ(-1200);
point.getScope().add(objGroup);
subRoot.getChildren().addAll(objGroup, subCam, ambient, point);
SubScene subScene = new SubScene(subRoot, 1920, 860, true, true);
subScene.setFill(Color.BLACK);
subScene.setCamera(subCam);
root.getChildren().addAll(subScene);
Rotate xRotate;
Rotate yRotate;
objGroup.getTransforms().setAll(
xRotate = new Rotate(0, Rotate.X_AXIS),
yRotate = new Rotate(0, Rotate.Y_AXIS)
);
xRotate.angleProperty().bind(angleX);
yRotate.angleProperty().bind(angleY);
subScene.setOnMousePressed(event -> {
anchorX = event.getSceneX();
anchorY = event.getSceneY();
anchorAngleX = angleX.get();
anchorAngleY = angleY.get();
});
subScene.setOnMouseDragged(event -> {
angleX.set(anchorAngleX - (anchorY - event.getSceneY()));
angleY.set(anchorAngleY + anchorX - event.getSceneX());
});
xSlider.valueProperty().bindBidirectional(xPos);
subCam.translateXProperty().bind(xPos);
ySlider.valueProperty().bindBidirectional(yPos);
subCam.translateYProperty().bind(yPos);
zSlider.valueProperty().bindBidirectional(zPos);
subCam.translateZProperty().bind(zPos);
sxSlider.valueProperty().bindBidirectional(sxPos);
subCam.scaleXProperty().bind(sxPos);
sySlider.valueProperty().bindBidirectional(syPos);
subCam.scaleYProperty().bind(syPos);
szSlider.valueProperty().bindBidirectional(szPos);
subCam.scaleZProperty().bind(szPos);
Rotate rxRotate;
Rotate ryRotate;
Rotate rzRotate;
subCam.getTransforms().setAll(
rxRotate = new Rotate(0, Rotate.X_AXIS),
ryRotate = new Rotate(0, Rotate.Y_AXIS),
rzRotate = new Rotate(0, Rotate.Z_AXIS)
);
rxRotate.angleProperty().bind(rxPos);
ryRotate.angleProperty().bind(ryPos);
rzRotate.angleProperty().bind(rzPos);
rxSlider.valueProperty().bindBidirectional(rxPos);
rySlider.valueProperty().bindBidirectional(ryPos);
rzSlider.valueProperty().bindBidirectional(rzPos);
meshCheckBox.selectedProperty().bindBidirectional(showWireframe);
btn.setOnAction((ActionEvent event) -> {
objGroup.setLayoutX(960);
objGroup.setLayoutY(430);
anchorAngleX = 0;
anchorAngleY = 0;
angleX.set(0);
angleY.set(0);
xSlider.setValue(0);
ySlider.setValue(0);
zSlider.setValue(0);
sxSlider.setValue(1.0);
sySlider.setValue(1.0);
szSlider.setValue(1.0);
rxSlider.setValue(0);
rySlider.setValue(0);
rzSlider.setValue(0);
});
primaryStage.setTitle("はじめての JavaFX 3D");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}