diff --git a/lucien/src/main/java/com/hellblazer/luciferase/lucien/animus/Rotor3f.java b/lucien/src/main/java/com/hellblazer/luciferase/lucien/animus/Rotor3f.java
index 3281dfc..e064be7 100644
--- a/lucien/src/main/java/com/hellblazer/luciferase/lucien/animus/Rotor3f.java
+++ b/lucien/src/main/java/com/hellblazer/luciferase/lucien/animus/Rotor3f.java
@@ -78,15 +78,31 @@ Vector3f b() {
}
};
- private static final Vector3f POS_X = new Vector3f(1, 0, 0);
- private static final Vector3f POS_Y = new Vector3f(0, 1, 0);
- private static final Vector3f POS_Z = new Vector3f(0, 0, 1);
+ private static final float HALF_PI = (float) (Math.PI / 2);
+ private static final Vector3f POS_X = new Vector3f(1, 0, 0);
+ private static final Vector3f POS_Y = new Vector3f(0, 1, 0);
+ private static final Vector3f POS_Z = new Vector3f(0, 0, 1);
+
+ public Rotor3f angle(float theta) {
+ return slerp(theta / 90);
+ }
/**
- * Spherical Linear Interpolation from axis A to axis B.
+ * Spherical Linear Interpolation around the axis by the supplied radians
*
- * @param t - the parameterization value
- * @return the Rotor3f corresponding to point (t) in the interpolation from a()
+ * @param theta - the radians of rotation about the axis
+ * @return the Rotor3f corresponding to rotation in the interpolation from a()
+ * to b()
+ */
+ public Rotor3f radians(float theta) {
+ return slerp(theta / HALF_PI);
+ }
+
+ /**
+ * Spherical Linear Interpolation around the axis by the supplied angle
+ *
+ * @param theta - the angle of rotation about the axis
+ * @return the Rotor3f corresponding to rotation in the interpolation from a()
* to b()
*/
public Rotor3f slerp(float t) {
@@ -356,6 +372,11 @@ public Matrix4f toMatrix() {
return result;
}
+ @Override
+ public String toString() {
+ return String.format("Rotor3f [a=%s, xy=%s, yz=%s, zx=%s]", a, xy, yz, zx);
+ }
+
/**
* Transform the vector using the receiver
*
diff --git a/portal/src/main/java/com/hellblazer/luciferase/portal/Animus.java b/portal/src/main/java/com/hellblazer/luciferase/portal/Animus.java
deleted file mode 100644
index 5059c91..0000000
--- a/portal/src/main/java/com/hellblazer/luciferase/portal/Animus.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * Copyright (C) 2023 Hal Hildebrand. All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU Affero General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-package com.hellblazer.luciferase.portal;
-
-import javax.vecmath.Vector3f;
-
-import com.hellblazer.luciferase.lucien.animus.Oriented;
-import com.hellblazer.luciferase.lucien.animus.Rotor3f;
-
-import javafx.beans.Observable;
-import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleObjectProperty;
-import javafx.beans.value.ObservableValue;
-import javafx.scene.Node;
-import javafx.scene.transform.Affine;
-import javafx.scene.transform.Translate;
-
-/**
- * Integrated control of position and orientation for a JavaFX node
- *
- * @author hal.hildebrand
- */
-public class Animus {
-
- private final N animated;
- private final ObjectProperty orientation = new SimpleObjectProperty<>();
- private final ObjectProperty position = new SimpleObjectProperty<>();
- private final Oriented tracking;
-
- public Animus(N animated) {
- this(new Oriented(), animated);
- }
-
- public Animus(Oriented tracking, N animated) {
- this.animated = animated;
- this.tracking = tracking;
- updateTransforms();
- position.set(new Vector3f(tracking));
- orientation.set(new Rotor3f(tracking.orientation()));
- position.addListener(p -> updatePosition(p));
- orientation.addListener(r -> updateOrientation(r));
- }
-
- /**
- * @return the JavaFX Node animated by this Orientable
- */
- public N getAnimated() {
- return animated;
- }
-
- /**
- * @return the Property used to orient the animated Node
- */
- public ObjectProperty getOrientation() {
- return orientation;
- }
-
- /**
- *
- * @return the Property used to position the animated Node
- */
- public ObjectProperty getPosition() {
- return position;
- }
-
- /**
- * Used to update the properties on state change
- */
- protected void update() {
- updateTransforms();
- position.set(new Vector3f(tracking));
- tracking.orientation().set(new Rotor3f(tracking.orientation()));
- }
-
- protected void updateTransforms() {
- final var t = animated.getTransforms();
- t.clear();
- t.addAll(translate(), transform());
- }
-
- private Affine transform() {
- final var m = tracking.orientation().toMatrix();
- var t = new Affine();
- t.setToTransform(m.getM00(), m.getM10(), m.getM20(), m.getM30(), m.getM01(), m.getM11(), m.getM21(), m.getM31(),
- m.getM02(), m.getM12(), m.getM22(), m.getM32());
- return t;
- }
-
- private Translate translate() {
- return new Translate(tracking.x, tracking.y, tracking.z);
- }
-
- private void updateOrientation(Observable r) {
- if (r instanceof ObservableValue o) {
- tracking.orientation().set((Rotor3f) o.getValue());
- }
- updateTransforms();
- }
-
- private void updatePosition(Observable p) {
- if (p instanceof ObservableValue o) {
- tracking.set((Vector3f) o.getValue());
- }
- updateTransforms();
- }
-}
diff --git a/portal/src/main/java/com/hellblazer/luciferase/portal/MagicMirror.java b/portal/src/main/java/com/hellblazer/luciferase/portal/MagicMirror.java
index 62d2462..b97078b 100644
--- a/portal/src/main/java/com/hellblazer/luciferase/portal/MagicMirror.java
+++ b/portal/src/main/java/com/hellblazer/luciferase/portal/MagicMirror.java
@@ -20,32 +20,32 @@
import static com.hellblazer.luciferase.lucien.animus.Rotor3f.PrincipalAxis.Y;
import static com.hellblazer.luciferase.lucien.animus.Rotor3f.PrincipalAxis.Z;
-import javax.vecmath.Point3f;
-import javax.vecmath.Vector3f;
-
import com.hellblazer.luciferase.lucien.animus.Rotor3f;
import com.hellblazer.luciferase.portal.CubicGrid.Neighborhood;
+import com.hellblazer.luciferase.portal.mesh.explorer.Xform;
import com.hellblazer.luciferase.portal.mesh.polyhedra.plato.Cube;
import javafx.application.Application;
import javafx.event.EventHandler;
+import javafx.geometry.Point3D;
import javafx.scene.Camera;
import javafx.scene.DepthTest;
import javafx.scene.Group;
-import javafx.scene.Node;
+import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
+import javafx.scene.transform.Rotate;
+import javafx.scene.transform.Translate;
import javafx.stage.Stage;
/**
* @author hal.hildebrand
*/
public abstract class MagicMirror extends Application {
-
public static class MouseHandler {
protected double mouseDeltaX;
protected double mouseDeltaY;
@@ -53,39 +53,71 @@ public static class MouseHandler {
protected double mouseOldY;
protected double mousePosX;
protected double mousePosY;
+ protected float rx;
+ protected float ry;
}
- public static final float CUBE_EDGE_LENGTH = (float) (Math.sqrt(2) / 2);
- public static final float TET_EDGE_LENGTH = 1;
- protected static final double AXIS_LENGTH = 250.0;
- protected static final double CONTROL_MULTIPLIER = 0.1;
- protected static final double MOUSE_SPEED = 0.1;
- protected static final double ROTATION_SPEED = 2.0;
- protected static final double SHIFT_MULTIPLIER = 10.0;
- protected static final double TRACK_SPEED = 0.3;
+ public static final float CUBE_EDGE_LENGTH = (float) (Math.sqrt(2) / 2);
+
+ public static final float TET_EDGE_LENGTH = 1;
+ protected static final float AXIS_LENGTH = 250.0f;
+ protected static final float CAMERA_FAR_CLIP = 10000.0f;
+ protected static final float CAMERA_INITIAL_DISTANCE = -450f;
+ protected static final float CAMERA_INITIAL_X_ANGLE = 70.0f;
+ protected static final float CAMERA_INITIAL_Y_ANGLE = 320.0f;
+ protected static final float CAMERA_NEAR_CLIP = 0.1f;
+ protected static final float CONTROL_MULTIPLIER = 0.1f;
+ protected static final float MOUSE_SPEED = 0.1f;
+ protected static final float ROTATION_SPEED = 2.0f;
+ protected static final float SHIFT_MULTIPLIER = 10.0f;
+ protected static final float TRACK_SPEED = 0.3f;
+
+ public static void lookAt(Point3D cameraPosition, Point3D lookAtPos, Camera cam) {
+ // Create direction vector
+ Point3D camDirection = lookAtPos.subtract(cameraPosition.getX(), cameraPosition.getY(), cameraPosition.getZ());
+ camDirection = camDirection.normalize();
+ double xRotation = Math.toDegrees(Math.asin(-camDirection.getY()));
+ double yRotation = Math.toDegrees(Math.atan2(camDirection.getX(), camDirection.getZ()));
+ Rotate rx = new Rotate(xRotation, cameraPosition.getX(), cameraPosition.getY(), cameraPosition.getZ(),
+ Rotate.X_AXIS);
+ Rotate ry = new Rotate(yRotation, cameraPosition.getX(), cameraPosition.getY(), cameraPosition.getZ(),
+ Rotate.Y_AXIS);
+ cam.getTransforms()
+ .addAll(ry, rx, new Translate(cameraPosition.getX(), cameraPosition.getY(), cameraPosition.getZ()));
+ }
public static void main(String[] args) {
launch(args);
}
- protected final Group axisGroup = new Group();
- protected Portal portal;
- protected final Group root = new Group();
- protected final Xform transformingGroup = new Xform();
- protected final Xform world = new Xform();
+ protected final Group axisGroup = new Group();
+ protected final PerspectiveCamera camera;
+ protected final OrientedGroup cameraTransform;
+ protected final Group root = new Group();
+ protected final Xform transformingGroup = new Xform();
+ protected final Xform world = new Xform();
public MagicMirror() {
super();
+
+ var t = new OrientedTxfm();
+ t.next(new OrientedTxfm()).next(new OrientedTxfm()).setRotate(0, 0, 180.0f);
+ t.setRotate(CAMERA_INITIAL_X_ANGLE, CAMERA_INITIAL_Y_ANGLE, 0);
+
+ cameraTransform = new OrientedGroup(t);
+ camera = new PerspectiveCamera(true);
+ cameraTransform.getChildren().add(camera);
}
@Override
public void start(Stage primaryStage) throws Exception {
root.getChildren().add(world);
root.setDepthTest(DepthTest.ENABLE);
- portal = portal();
-
- world.getChildren().addAll(portal.getAvatar().getAnimated(), portal.getCamera().getAnimated());
+ root.getChildren().add(cameraTransform);
+ camera.setNearClip(CAMERA_NEAR_CLIP);
+ camera.setFarClip(CAMERA_FAR_CLIP);
+ camera.setTranslateZ(CAMERA_INITIAL_DISTANCE / 4);
buildAxes();
Scene scene = new Scene(root, 1024, 768, true, SceneAntialiasing.BALANCED);
@@ -97,8 +129,7 @@ public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(scene);
primaryStage.show();
- portal.setCamera(scene);
- resetCameraDefault();
+ scene.setCamera(camera);
// Attach a scroll listener
primaryStage.addEventHandler(ScrollEvent.SCROLL, event -> {
@@ -110,16 +141,12 @@ public void start(Stage primaryStage) throws Exception {
if (event.isShiftDown()) {
modifier = 100.0f;
}
- var position = portal.getCamera().getPosition();
-
- final var p = position.get();
- p.z = (float) (p.z + event.getDeltaY() * modifierFactor * modifier);
- position.set(p);
+ double z = camera.getTranslateZ();
+ double newZ = z + event.getDeltaY() * modifierFactor * modifier;
+ camera.setTranslateZ(newZ);
});
}
- abstract protected Animus animus();
-
protected void buildAxes() {
final var cubic = new CubicGrid(Neighborhood.EIGHT, new Cube(CUBE_EDGE_LENGTH), 1);
cubic.addAxes(axisGroup, 0.1, 0.2, 0.008, 20);
@@ -127,8 +154,6 @@ protected void buildAxes() {
world.getChildren().addAll(axisGroup);
}
- abstract protected Animus camera();
-
protected void handleKeyboard(Scene scene) {
scene.setOnKeyPressed(new EventHandler() {
@@ -136,7 +161,7 @@ protected void handleKeyboard(Scene scene) {
public void handle(KeyEvent event) {
switch (event.getCode()) {
case Z:
- resetCameraDefault();
+ cameraTransform.getTransform().reset();
break;
case X:
axisGroup.setVisible(!axisGroup.isVisible());
@@ -153,8 +178,6 @@ public void handle(KeyEvent event) {
protected MouseHandler handleMouse(Scene scene) {
var h = new MouseHandler();
- final var position = portal.getCamera().getPosition();
- final var orientation = portal.getCamera().getOrientation();
scene.setOnMousePressed(new EventHandler() {
@Override
@@ -183,33 +206,24 @@ public void handle(MouseEvent me) {
if (me.isShiftDown()) {
modifier = SHIFT_MULTIPLIER;
}
-
+ var t = cameraTransform.getTransform();
if (me.isMiddleButtonDown() || (me.isPrimaryButtonDown() && me.isSecondaryButtonDown())) {
- var p = new Vector3f(position.get());
- p.add(new Point3f((float) (h.mouseDeltaX * MOUSE_SPEED * modifier * TRACK_SPEED),
- (float) (h.mouseDeltaY * MOUSE_SPEED * modifier * TRACK_SPEED), 0f));
- position.set(p);
+ t.t.setX((float) (t.t.getX() + h.mouseDeltaX * MOUSE_SPEED * modifier * TRACK_SPEED));
+ t.next.t.setY(t.next.t.getY() + h.mouseDeltaY * MOUSE_SPEED * modifier * TRACK_SPEED);
} else if (me.isPrimaryButtonDown()) {
- var o = new Rotor3f(orientation.get());
- o.combine(X.slerp((float) (-h.mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED)))
- .combine(Y.slerp((float) (h.mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED)));
- orientation.set(o);
+ h.ry = (float) (h.ry - h.mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED);
+ h.rx = (float) (h.rx + h.mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED);
+ t.setRotate(h.rx, h.ry, 0);
} else if (me.isSecondaryButtonDown()) {
- var p = new Vector3f(position.get());
- p.z = (float) (p.z + h.mouseDeltaX * MOUSE_SPEED * modifier);
- position.set(p);
+ double z = camera.getTranslateZ();
+ double newZ = z + h.mouseDeltaX * MOUSE_SPEED * modifier;
+ camera.setTranslateZ(newZ);
}
}
});
return h;
}
- protected Portal portal() {
- return new Portal(animus(), camera());
- }
-
- abstract protected void resetCameraDefault();
-
protected Rotor3f rotation(KeyEvent event, float t) {
return switch (event.getCode()) {
case A -> X.slerp(t);
diff --git a/portal/src/main/java/com/hellblazer/luciferase/portal/Portal.java b/portal/src/main/java/com/hellblazer/luciferase/portal/OrientedGroup.java
similarity index 56%
rename from portal/src/main/java/com/hellblazer/luciferase/portal/Portal.java
rename to portal/src/main/java/com/hellblazer/luciferase/portal/OrientedGroup.java
index 506e0f7..da3c706 100644
--- a/portal/src/main/java/com/hellblazer/luciferase/portal/Portal.java
+++ b/portal/src/main/java/com/hellblazer/luciferase/portal/OrientedGroup.java
@@ -16,35 +16,26 @@
*/
package com.hellblazer.luciferase.portal;
-import javafx.scene.Camera;
-import javafx.scene.Node;
-import javafx.scene.Scene;
+import javafx.scene.Group;
/**
+ * A group that encapsulates a chain of oriented transforms
+ *
* @author hal.hildebrand
*/
-public class Portal {
- private final Animus avatar;
- private final Animus camera;
+public class OrientedGroup extends Group {
+ private final OrientedTxfm txfm;
- public Portal(Animus avatar, Animus camera) {
- this.avatar = avatar;
- this.camera = camera;
+ public OrientedGroup(OrientedTxfm txfm) {
+ this.txfm = txfm;
+ apply();
}
- public Portal(Node avatar, Camera camera) {
- this(new Animus<>(avatar), new Animus<>(camera));
+ public void apply() {
+ txfm.accept(this);
}
- public Animus getAvatar() {
- return avatar;
- }
-
- public Animus getCamera() {
- return camera;
- }
-
- public void setCamera(Scene scene) {
- scene.setCamera(camera.getAnimated());
+ public OrientedTxfm getTransform() {
+ return txfm;
}
}
diff --git a/portal/src/main/java/com/hellblazer/luciferase/portal/OrientedTxfm.java b/portal/src/main/java/com/hellblazer/luciferase/portal/OrientedTxfm.java
new file mode 100644
index 0000000..5f78424
--- /dev/null
+++ b/portal/src/main/java/com/hellblazer/luciferase/portal/OrientedTxfm.java
@@ -0,0 +1,184 @@
+/**
+ * Copyright (C) 2023 Hal Hildebrand. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Affero General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package com.hellblazer.luciferase.portal;
+
+import static com.hellblazer.luciferase.lucien.animus.Rotor3f.PrincipalAxis.X;
+import static com.hellblazer.luciferase.lucien.animus.Rotor3f.PrincipalAxis.Y;
+import static com.hellblazer.luciferase.lucien.animus.Rotor3f.PrincipalAxis.Z;
+
+import java.util.function.Consumer;
+
+import javax.vecmath.Tuple3f;
+
+import com.hellblazer.luciferase.lucien.animus.Rotor3f;
+
+import javafx.scene.Node;
+import javafx.scene.transform.Affine;
+import javafx.scene.transform.Scale;
+import javafx.scene.transform.Translate;
+
+/**
+ * Composable transform. This is a Translate, followed by the transform to the
+ * orientation and then finally the scaling. This class is designed to be
+ * chained together to perform complex transformations and then to apply these
+ * transformations to any given Node.
+ *
+ * @author hal.hildebrand
+ */
+public class OrientedTxfm implements Consumer {
+ OrientedTxfm next;
+ final Rotor3f orientation = new Rotor3f();
+ final Scale s = new Scale();
+ final Translate t = new Translate();
+
+ @Override
+ public void accept(Node node) {
+ final var transforms = node.getTransforms();
+ transforms.clear();
+ var current = this;
+ while (current != null) {
+ transforms.addAll(current.t, current.transform(), current.s);
+ current = current.next;
+ }
+ }
+
+ /**
+ * Set the next txfm of the receiver, return the txfm
+ *
+ * @param txfm
+ * @return the passed txfm
+ */
+ public OrientedTxfm next(OrientedTxfm txfm) {
+ next = txfm;
+ return txfm;
+ }
+
+ /**
+ * Reset to zero'd state
+ */
+ public void reset() {
+ t.setX(0.0);
+ t.setY(0.0);
+ t.setZ(0.0);
+ orientation.set(new Rotor3f());
+ s.setX(1.0);
+ s.setY(1.0);
+ s.setZ(1.0);
+ }
+
+ /**
+ * Reset translate and scale
+ */
+ public void resetTS() {
+ t.setX(0.0);
+ t.setY(0.0);
+ t.setZ(0.0);
+ s.setX(1.0);
+ s.setY(1.0);
+ s.setZ(1.0);
+ }
+
+ public void setOrientation(Rotor3f orientation) {
+ this.orientation.set(orientation);
+ }
+
+ /**
+ * set the orientation to the supplied angles rotation around the primary axis
+ *
+ * @param x
+ * @param y
+ * @param z
+ */
+ public void setRotate(float x, float y, float z) {
+ orientation.set(X.angle(-x).combine(Y.angle(-y)).combine(Z.angle(z)));
+ }
+
+ /**
+ * scale everything
+ *
+ * @param scaleFactor
+ */
+ public void setScale(double scaleFactor) {
+ s.setX(scaleFactor);
+ s.setY(scaleFactor);
+ s.setZ(scaleFactor);
+ }
+
+ /**
+ * Scale by component
+ */
+ public void setScale(double x, double y, double z) {
+ s.setX(x);
+ s.setY(y);
+ s.setZ(z);
+ }
+
+ public void setScaleX(double x) {
+ s.setX(x);
+ }
+
+ public void setScaleY(double y) {
+ s.setY(y);
+ }
+
+ public void setScaleZ(double z) {
+ s.setZ(z);
+ }
+
+ public void setTranslate(double x, double y) {
+ t.setX(x);
+ t.setY(y);
+ }
+
+ public void setTranslate(double x, double y, double z) {
+ t.setX(x);
+ t.setY(y);
+ t.setZ(z);
+ }
+
+ public void setTranslate(Tuple3f p) {
+ t.setX(p.x);
+ t.setY(p.y);
+ t.setZ(p.z);
+ }
+
+ public void setTranslateX(double x) {
+ t.setX(x);
+ }
+
+ public void setTranslateY(double y) {
+ t.setY(y);
+ }
+
+ public void setTranslateZ(double z) {
+ t.setZ(z);
+ }
+
+ @Override
+ public String toString() {
+ return "OrientedTxfm[t = (" + t.getX() + ", " + t.getY() + ", " + t.getZ() + ") " + "r = (" + orientation
+ + ") " + "s = (" + s.getX() + ", " + s.getY() + ", " + s.getZ() + ")]";
+ }
+
+ private Affine transform() {
+ final var m = orientation.toMatrix();
+ var t = new Affine();
+ t.setToTransform(m.getM00(), m.getM10(), m.getM20(), m.getM30(), m.getM01(), m.getM11(), m.getM21(), m.getM31(),
+ m.getM02(), m.getM12(), m.getM22(), m.getM32());
+ return t;
+ }
+}
diff --git a/portal/src/main/java/com/hellblazer/luciferase/portal/Scaled.java b/portal/src/main/java/com/hellblazer/luciferase/portal/Scaled.java
deleted file mode 100644
index cef2ec7..0000000
--- a/portal/src/main/java/com/hellblazer/luciferase/portal/Scaled.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Copyright (C) 2023 Hal Hildebrand. All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU Affero General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-package com.hellblazer.luciferase.portal;
-
-import com.hellblazer.luciferase.lucien.animus.Oriented;
-
-import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleObjectProperty;
-import javafx.scene.Node;
-import javafx.scene.transform.Scale;
-
-/**
- * Scaled Animus
- *
- * @author hal.hildebrand
- */
-public class Scaled extends Animus {
- private final ObjectProperty scale;
-
- public Scaled(N animated) {
- this(new Oriented(), animated);
- }
-
- public Scaled(Oriented tracking, N animated) {
- this(tracking, animated, new Scale());
- }
-
- public Scaled(Oriented tracking, N animated, Scale scale) {
- super(tracking, animated);
- this.scale = new SimpleObjectProperty<>(scale);
- }
-
- @Override
- protected void updateTransforms() {
- super.updateTransforms();
- getAnimated().getTransforms().add(scale.getValue());
- }
-}
diff --git a/portal/src/main/java/com/hellblazer/luciferase/portal/mesh/explorer/Abstract3DApp.java b/portal/src/main/java/com/hellblazer/luciferase/portal/mesh/explorer/Abstract3DApp.java
index b5e4a6d..62cfccd 100644
--- a/portal/src/main/java/com/hellblazer/luciferase/portal/mesh/explorer/Abstract3DApp.java
+++ b/portal/src/main/java/com/hellblazer/luciferase/portal/mesh/explorer/Abstract3DApp.java
@@ -18,7 +18,6 @@
import com.hellblazer.luciferase.portal.CubicGrid;
import com.hellblazer.luciferase.portal.CubicGrid.Neighborhood;
-import com.hellblazer.luciferase.portal.Xform;
import com.hellblazer.luciferase.portal.mesh.polyhedra.plato.Cube;
import javafx.application.Application;
@@ -39,17 +38,17 @@
*/
public abstract class Abstract3DApp extends Application {
- public static final float CUBE_EDGE_LENGTH = (float) (Math.sqrt(2) / 2);
- protected static final double AXIS_LENGTH = 250.0;
- protected static final double CAMERA_FAR_CLIP = 10000.0;
- protected static final double CAMERA_INITIAL_DISTANCE = -450;
- protected static final double CAMERA_INITIAL_X_ANGLE = 70.0;
- protected static final double CAMERA_INITIAL_Y_ANGLE = 320.0;
- protected static final double CAMERA_NEAR_CLIP = 0.1;
- protected static final double CONTROL_MULTIPLIER = 0.1;
- protected static final double MOUSE_SPEED = 0.1;
- protected static final double ROTATION_SPEED = 2.0;
- protected static final double SHIFT_MULTIPLIER = 10.0;
+ public static final float CUBE_EDGE_LENGTH = (float) (Math.sqrt(2) / 2);
+ protected static final float AXIS_LENGTH = 250.0f;
+ protected static final float CAMERA_FAR_CLIP = 10000.0f;
+ protected static final float CAMERA_INITIAL_DISTANCE = -450;
+ protected static final float CAMERA_INITIAL_X_ANGLE = 70.0f;
+ protected static final float CAMERA_INITIAL_Y_ANGLE = 320.0f;
+ protected static final float CAMERA_NEAR_CLIP = 0.1f;
+ protected static final float CONTROL_MULTIPLIER = 0.1f;
+ protected static final float MOUSE_SPEED = 0.1f;
+ protected static final float ROTATION_SPEED = 2.0f;
+ protected static final float SHIFT_MULTIPLIER = 10.0f;
protected static final double TRACK_SPEED = 0.3;
protected final Xform axisGroup = new Xform();
diff --git a/portal/src/main/java/com/hellblazer/luciferase/portal/Xform.java b/portal/src/main/java/com/hellblazer/luciferase/portal/mesh/explorer/Xform.java
similarity index 95%
rename from portal/src/main/java/com/hellblazer/luciferase/portal/Xform.java
rename to portal/src/main/java/com/hellblazer/luciferase/portal/mesh/explorer/Xform.java
index e07db62..4ac3c69 100644
--- a/portal/src/main/java/com/hellblazer/luciferase/portal/Xform.java
+++ b/portal/src/main/java/com/hellblazer/luciferase/portal/mesh/explorer/Xform.java
@@ -30,7 +30,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package com.hellblazer.luciferase.portal;
+package com.hellblazer.luciferase.portal.mesh.explorer;
import javafx.scene.Group;
import javafx.scene.transform.Rotate;
diff --git a/portal/src/test/java/com/hellblazer/luciferase/portal/TestPortal.java b/portal/src/test/java/com/hellblazer/luciferase/portal/TestPortal.java
index 91de6a6..14ad1e8 100644
--- a/portal/src/test/java/com/hellblazer/luciferase/portal/TestPortal.java
+++ b/portal/src/test/java/com/hellblazer/luciferase/portal/TestPortal.java
@@ -18,7 +18,7 @@
import java.util.Set;
-import javax.vecmath.Vector3f;
+import javax.vecmath.Point3f;
import com.hellblazer.luciferase.portal.CubicGrid.Neighborhood;
import com.hellblazer.luciferase.portal.mesh.Edge;
@@ -28,10 +28,8 @@
import com.hellblazer.luciferase.portal.mesh.polyhedra.archimedes.Cuboctahedron;
import com.hellblazer.luciferase.portal.mesh.polyhedra.plato.Cube;
-import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.Node;
-import javafx.scene.PerspectiveCamera;
import javafx.scene.paint.Material;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.MeshView;
@@ -51,12 +49,6 @@ public static void main(String[] argv) {
}
}
- protected static final float CAMERA_FAR_CLIP = 10000.0f;
- protected static final float CAMERA_INITIAL_DISTANCE = -450f;
- protected static final float CAMERA_INITIAL_X_ANGLE = 70.0f;
- protected static final float CAMERA_INITIAL_Y_ANGLE = 320.0f;
- protected static final float CAMERA_NEAR_CLIP = 0.1f;
-
public static void add(final Polyhedron polyhedron, Group view) {
MeshView v = new MeshView(polyhedron.toTriangleMesh().constructMesh());
v.setMaterial(Colors.cyanMaterial);
@@ -85,61 +77,19 @@ public static void main(String[] args) {
launch(args);
}
- protected final Xform cameraXform = new Xform();
-
- protected final Xform cameraXform2 = new Xform();
+ protected Node content() {
+ OrientedTxfm txfm = new OrientedTxfm();
+ txfm.setTranslate(new Point3f(0, 0, 2));
+ txfm.setRotate(45, 45, -45);
+ var view = new OrientedGroup(txfm);
- protected final Xform cameraXform3 = new Xform();
-
- @Override
- protected Animus animus() {
- var view = new Group();
final var cubic = new CubicGrid(Neighborhood.EIGHT, new Cube(CUBE_EDGE_LENGTH), 1);
cubic.addAxes(view, 0.1, 0.2, 0.008, 20);
Polyhedron polyhedron = new Cuboctahedron(TET_EDGE_LENGTH);
var dual = polyhedron.dual();
var dualEdges = dual.getEdges();
-
addEdges(dualEdges, Colors.redMaterial, view);
- var animus = new Animus(view);
-
- var p = new Vector3f();
- p.z = p.z + 2;
- animus.getPosition().set(p);
-// animus.getOrientation().set(PrincipalAxis.Y.slerp(-0.5f).combine(PrincipalAxis.Z.slerp(0.5f)));
-
- return animus;
- }
-
- @Override
- protected Animus camera() {
- final var camera = new PerspectiveCamera(true);
- final Animus animus = new Animus<>(camera);
- return animus;
- }
-
- @Override
- protected void resetCameraDefault() {
- final var camera = portal.getCamera().getAnimated();
- root.getChildren().add(cameraXform);
- cameraXform.getChildren().add(cameraXform2);
- cameraXform2.getChildren().add(cameraXform3);
- cameraXform3.getChildren().add(camera);
- cameraXform3.setRotateZ(180.0);
-
- camera.setNearClip(CAMERA_NEAR_CLIP);
- camera.setFarClip(CAMERA_FAR_CLIP);
- camera.setTranslateZ(CAMERA_INITIAL_DISTANCE / 4);
- cameraXform.ry.setAngle(CAMERA_INITIAL_Y_ANGLE);
- cameraXform.rx.setAngle(CAMERA_INITIAL_X_ANGLE);
-
-// final var camera = portal.getCamera();
-// root.getChildren().add(camera.getAnimated());
-// camera.getAnimated().setNearClip(CAMERA_NEAR_CLIP);
-// camera.getAnimated().setFarClip(CAMERA_FAR_CLIP);
-//
-// camera.getPosition().set(new Vector3f(0, 0, -CAMERA_INITIAL_DISTANCE / 4));
-// camera.getOrientation().set(PrincipalAxis.Y.slerp(2f));
+ return view;
}
@Override
diff --git a/portal/src/test/java/com/hellblazer/luciferase/portal/Viewer.java b/portal/src/test/java/com/hellblazer/luciferase/portal/Viewer.java
index 1dc3667..9b85e23 100644
--- a/portal/src/test/java/com/hellblazer/luciferase/portal/Viewer.java
+++ b/portal/src/test/java/com/hellblazer/luciferase/portal/Viewer.java
@@ -19,6 +19,7 @@
import static com.hellblazer.luciferase.portal.MagicMirror.TET_EDGE_LENGTH;
import static com.hellblazer.luciferase.portal.TestPortal.addEdges;
+import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import com.hellblazer.luciferase.portal.CubicGrid.Neighborhood;
@@ -50,11 +51,11 @@ public static void main(String[] args) {
launch(args);
}
- private Animus animus;
- private Animus fauxCamera;
-
protected Node animus() {
- var view = new Group();
+ OrientedTxfm txfm = new OrientedTxfm();
+ txfm.setTranslate(new Point3f(0, 0, 2));
+ txfm.setRotate(45, 45, -45);
+ var view = new OrientedGroup(txfm);
final var cubic = new CubicGrid(Neighborhood.EIGHT, new Cube(CUBE_EDGE_LENGTH), 1);
cubic.addAxes(view, 0.1, 0.2, 0.008, 20);
Polyhedron polyhedron = new Cuboctahedron(TET_EDGE_LENGTH);
@@ -62,14 +63,7 @@ protected Node animus() {
var dualEdges = dual.getEdges();
addEdges(dualEdges, Colors.redMaterial, view);
- animus = new Animus(view);
-
- var p = new Vector3f();
- p.z = p.z + 2;
- animus.getPosition().set(p);
-// animus.getOrientation().set(PrincipalAxis.Y.slerp(-0.5f).combine(PrincipalAxis.Z.slerp(0.5f)));
-
- return animus.getAnimated();
+ return view;
}
@Override
@@ -77,14 +71,17 @@ protected Group build() {
var g = new Group();
g.getChildren().add(animus());
final var cubic = new CubicGrid(Neighborhood.EIGHT, new Cube(CUBE_EDGE_LENGTH), 1);
-// cubic.addAxes(g, 0.1, 0.2, 0.008, 20);
- fauxCamera = new Animus<>(new Group());
- cubic.addAxes(fauxCamera.getAnimated(), 0.1, 0.2, 0.008, 20);
- g.getChildren().add(fauxCamera.getAnimated());
+ var fauxCamera = new Group();
+ cubic.addAxes(fauxCamera, 0.1, 0.2, 0.008, 20);
+ g.getChildren().add(fauxCamera);
+
+ var t = new OrientedTxfm();
+ t.next(new OrientedTxfm()).next(new OrientedTxfm()).setRotate(0, 0, 180.0f);
+ t.setRotate(CAMERA_INITIAL_X_ANGLE, CAMERA_INITIAL_Y_ANGLE, 0);
+ t.setTranslate(new Vector3f(0, 0, 20));
- fauxCamera.getPosition().set(new Vector3f(0, 0, -20));
-// fauxCamera.getOrientation().set(PrincipalAxis.Y.slerp(2f));
+ t.accept(fauxCamera);
return g;
}