From 04dc9cb868851648f00236ebd5aa98e78b8254f0 Mon Sep 17 00:00:00 2001 From: James Ball Date: Mon, 17 May 2021 19:54:27 +0100 Subject: [PATCH 1/4] Implement code and GUI elements for updating the rotation of objects --- src/main/java/sh/ball/engine/Vector3.java | 1 + src/main/java/sh/ball/engine/WorldObject.java | 1 - src/main/java/sh/ball/gui/Controller.java | 33 ++++++++++++++++++- .../java/sh/ball/parser/obj/ObjFrameSet.java | 27 ++++++++------- .../sh/ball/parser/obj/ObjFrameSettings.java | 16 +++++++-- .../java/sh/ball/parser/obj/ObjParser.java | 15 ++------- src/main/resources/fxml/osci-render.fxml | 24 ++++++++++---- 7 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/main/java/sh/ball/engine/Vector3.java b/src/main/java/sh/ball/engine/Vector3.java index 9adbfb5..01c217c 100644 --- a/src/main/java/sh/ball/engine/Vector3.java +++ b/src/main/java/sh/ball/engine/Vector3.java @@ -79,6 +79,7 @@ public final class Vector3 { ); } + // TODO: Is this correctly used?! public double distance(Vector3 vector) { return Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2) + Math.pow(vector.z, 2)); } diff --git a/src/main/java/sh/ball/engine/WorldObject.java b/src/main/java/sh/ball/engine/WorldObject.java index 3cf7daa..71169f9 100644 --- a/src/main/java/sh/ball/engine/WorldObject.java +++ b/src/main/java/sh/ball/engine/WorldObject.java @@ -2,7 +2,6 @@ package sh.ball.engine; import com.mokiat.data.front.parser.*; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; diff --git a/src/main/java/sh/ball/gui/Controller.java b/src/main/java/sh/ball/gui/Controller.java index e2b15cf..a8f122c 100644 --- a/src/main/java/sh/ball/gui/Controller.java +++ b/src/main/java/sh/ball/gui/Controller.java @@ -40,6 +40,7 @@ public class Controller implements Initializable { private static final int SAMPLE_RATE = 192000; private static final InputStream DEFAULT_OBJ = Controller.class.getResourceAsStream("/models/cube.obj"); + private static final double DEFAULT_ROTATE_SPEED = 0.1; private final FileChooser fileChooser = new FileChooser(); private final Renderer> renderer; @@ -90,6 +91,16 @@ public class Controller implements Initializable { @FXML private TextField cameraZTextField; @FXML + private Slider objectRotateSpeedSlider; + @FXML + private Label objectRotateSpeedLabel; + @FXML + private TextField rotateXTextField; + @FXML + private TextField rotateYTextField; + @FXML + private TextField rotateZTextField; + @FXML private CheckBox vectorCancellingCheckBox; @FXML private Slider vectorCancellingSlider; @@ -117,7 +128,9 @@ public class Controller implements Initializable { scaleSlider, new SliderUpdater<>(scaleLabel::setText, scaleEffect::setScale), focalLengthSlider, - new SliderUpdater<>(focalLengthLabel::setText, this::setFocalLength) + new SliderUpdater<>(focalLengthLabel::setText, this::setFocalLength), + objectRotateSpeedSlider, + new SliderUpdater<>(objectRotateSpeedLabel::setText, this::setObjectRotateSpeed) ); } @@ -132,6 +145,7 @@ public class Controller implements Initializable { ); } + // TODO: Refactor and clean up duplication @Override public void initialize(URL url, ResourceBundle resourceBundle) { Map> sliders = initializeSliderMap(); @@ -163,6 +177,17 @@ public class Controller implements Initializable { cameraYTextField.textProperty().addListener(cameraPosUpdate); cameraZTextField.textProperty().addListener(cameraPosUpdate); + InvalidationListener rotateUpdate = observable -> + producer.setFrameSettings(new ObjFrameSettings(new Vector3( + tryParse(rotateXTextField.getText()), + tryParse(rotateYTextField.getText()), + tryParse(rotateZTextField.getText()) + ), null)); + + rotateXTextField.textProperty().addListener(rotateUpdate); + rotateYTextField.textProperty().addListener(rotateUpdate); + rotateZTextField.textProperty().addListener(rotateUpdate); + InvalidationListener vectorCancellingListener = e -> updateEffect(EffectType.VECTOR_CANCELLING, vectorCancellingCheckBox.isSelected(), EffectFactory.vectorCancelling((int) vectorCancellingSlider.getValue())); @@ -183,6 +208,8 @@ public class Controller implements Initializable { } }); + setObjectRotateSpeed(DEFAULT_ROTATE_SPEED); + renderer.addEffect(EffectType.SCALE, scaleEffect); renderer.addEffect(EffectType.ROTATE, rotateEffect); renderer.addEffect(EffectType.TRANSLATE, translateEffect); @@ -198,6 +225,10 @@ public class Controller implements Initializable { cameraZTextField.setText(String.valueOf(pos.getZ())); } + private void setObjectRotateSpeed(double rotateSpeed) { + producer.setFrameSettings(new ObjFrameSettings(null, (Math.exp(3 * rotateSpeed) - 1) / 50)); + } + private double tryParse(String value) { try { return Double.parseDouble(value); diff --git a/src/main/java/sh/ball/parser/obj/ObjFrameSet.java b/src/main/java/sh/ball/parser/obj/ObjFrameSet.java index 278d709..fb6f00c 100644 --- a/src/main/java/sh/ball/parser/obj/ObjFrameSet.java +++ b/src/main/java/sh/ball/parser/obj/ObjFrameSet.java @@ -12,36 +12,41 @@ public class ObjFrameSet implements FrameSet> { private final WorldObject object; private final Camera camera; - private final Vector3 rotation; private final boolean isDefaultPosition; - public ObjFrameSet(WorldObject object, Camera camera, Vector3 rotation, boolean isDefaultPosition) { + private Vector3 rotation = new Vector3(); + private Double rotateSpeed = 0.0; + + public ObjFrameSet(WorldObject object, Camera camera, boolean isDefaultPosition) { this.object = object; this.camera = camera; - this.rotation = rotation; this.isDefaultPosition = isDefaultPosition; } @Override public List next() { - object.rotate(rotation); + object.rotate(rotation.scale(rotateSpeed)); return camera.draw(object); } + // TODO: Refactor! @Override public Object setFrameSettings(Object settings) { if (settings instanceof ObjFrameSettings obj) { - Double focalLength = obj.focalLength(); - Vector3 cameraPos = obj.cameraPos(); - - if (focalLength != null && camera.getFocalLength() != focalLength) { - camera.setFocalLength(focalLength); + if (obj.focalLength != null && camera.getFocalLength() != obj.focalLength) { + camera.setFocalLength(obj.focalLength); if (isDefaultPosition) { camera.findZPos(object); } } - if (cameraPos != null && camera.getPos() != cameraPos) { - camera.setPos(cameraPos); + if (obj.cameraPos != null && camera.getPos() != obj.cameraPos) { + camera.setPos(obj.cameraPos); + } + if (obj.rotation != null) { + this.rotation = obj.rotation; + } + if (obj.rotateSpeed != null) { + this.rotateSpeed = obj.rotateSpeed; } } diff --git a/src/main/java/sh/ball/parser/obj/ObjFrameSettings.java b/src/main/java/sh/ball/parser/obj/ObjFrameSettings.java index 70820c6..845d28a 100644 --- a/src/main/java/sh/ball/parser/obj/ObjFrameSettings.java +++ b/src/main/java/sh/ball/parser/obj/ObjFrameSettings.java @@ -2,13 +2,23 @@ package sh.ball.parser.obj; import sh.ball.engine.Vector3; -public record ObjFrameSettings(Double focalLength, Vector3 cameraPos) { +public class ObjFrameSettings { + + protected Double focalLength; + protected Vector3 cameraPos; + protected Vector3 rotation; + protected Double rotateSpeed; public ObjFrameSettings(double focalLength) { - this(focalLength, null); + this.focalLength = focalLength; } public ObjFrameSettings(Vector3 cameraPos) { - this(null, cameraPos); + this.cameraPos = cameraPos; + } + + public ObjFrameSettings(Vector3 rotation, Double rotateSpeed) { + this.rotation = rotation; + this.rotateSpeed = rotateSpeed; } } diff --git a/src/main/java/sh/ball/parser/obj/ObjParser.java b/src/main/java/sh/ball/parser/obj/ObjParser.java index 222f1cd..ba22bcb 100644 --- a/src/main/java/sh/ball/parser/obj/ObjParser.java +++ b/src/main/java/sh/ball/parser/obj/ObjParser.java @@ -16,27 +16,22 @@ import sh.ball.shapes.Shape; public class ObjParser extends FileParser>> { - private static final float DEFAULT_ROTATE_SPEED = 3; - - private final Vector3 rotation; private final boolean isDefaultPosition; private final InputStream input; private final Camera camera; private WorldObject object; - public ObjParser(InputStream input, float rotateSpeed, float cameraX, float cameraY, float cameraZ, + public ObjParser(InputStream input, float cameraX, float cameraY, float cameraZ, float focalLength, boolean isDefaultPosition) { - rotateSpeed *= Math.PI / 1000; this.input = input; this.isDefaultPosition = isDefaultPosition; Vector3 cameraPos = new Vector3(cameraX, cameraY, cameraZ); this.camera = new Camera(focalLength, cameraPos); - this.rotation = new Vector3(0, rotateSpeed, rotateSpeed); } public ObjParser(InputStream input, float focalLength) { - this(input, DEFAULT_ROTATE_SPEED, 0, 0, 0, focalLength, true); + this(input, 0, 0, 0, focalLength, true); } public ObjParser(InputStream input) { @@ -60,7 +55,7 @@ public class ObjParser extends FileParser>> { camera.findZPos(object); } - return new ObjFrameSet(object, camera, rotation, isDefaultPosition); + return new ObjFrameSet(object, camera, isDefaultPosition); } // If camera position arguments haven't been specified, automatically work out the position of @@ -75,8 +70,4 @@ public class ObjParser extends FileParser>> { public static boolean isObjFile(String path) { return path.matches(".*\\.obj"); } - - public void setCameraPos(Vector3 vector) { - camera.setPos(vector); - } } diff --git a/src/main/resources/fxml/osci-render.fxml b/src/main/resources/fxml/osci-render.fxml index 4741300..3454e8e 100644 --- a/src/main/resources/fxml/osci-render.fxml +++ b/src/main/resources/fxml/osci-render.fxml @@ -58,13 +58,23 @@