diff --git a/src/audio/AudioClient.java b/src/audio/AudioClient.java index 4b7d80cb..2a445479 100644 --- a/src/audio/AudioClient.java +++ b/src/audio/AudioClient.java @@ -14,20 +14,30 @@ public class AudioClient { public static final int SAMPLE_RATE = 192000; public static final double TARGET_FRAMERATE = 30; + private static final double OBJ_ROTATE = Math.PI / 100; + private static final float ROTATE_SPEED = 0; + private static final float TRANSLATION_SPEED = 0; + private static final Vector2 TRANSLATION = new Vector2(1, 1); + private static final float SCALE = 2; + private static final float WEIGHT = 100; + public static void main(String[] args) { // TODO: Calculate weight of lines using depth. // Reduce weight of lines drawn multiple times. // Find intersections of lines to (possibly) improve line cleanup. // Improve performance of line cleanup with a heuristic. - Camera camera = new Camera(0.6, new Vector3(0, 0, -0.08)); - WorldObject object = new WorldObject(args[0], new Vector3(0, 0, 0), new Vector3()); - Vector3 rotation = new Vector3(0,Math.PI / 100,Math.PI / 100); - List> preRenderedFrames = new ArrayList<>(); - + String objFilePath = args[0]; int numFrames = (int) (Float.parseFloat(args[1]) * TARGET_FRAMERATE); + float focalLength = Float.parseFloat(args[2]); + float cameraX = Float.parseFloat(args[3]); + float cameraY = Float.parseFloat(args[4]); + float cameraZ = Float.parseFloat(args[5]); - long start = System.currentTimeMillis(); + Camera camera = new Camera(focalLength, new Vector3(cameraX, cameraY, cameraZ)); + WorldObject object = new WorldObject(objFilePath); + Vector3 rotation = new Vector3(0, OBJ_ROTATE, OBJ_ROTATE); + List> preRenderedFrames = new ArrayList<>(); for (int i = 0; i < numFrames; i++) { preRenderedFrames.add(new ArrayList<>()); @@ -39,11 +49,10 @@ public class AudioClient { preRenderedFrames.set(frameNum, Shapes.sortLines(camera.draw(clone))); }); - System.out.println(System.currentTimeMillis() - start); - AudioPlayer player = new AudioPlayer(SAMPLE_RATE, preRenderedFrames); - //AudioPlayer.setRotateSpeed(1); - //AudioPlayer.setTranslation(1, new Vector2(1, 1)); + player.setRotateSpeed(ROTATE_SPEED); + player.setTranslation(TRANSLATION_SPEED, TRANSLATION); + player.setScale(SCALE); player.start(); } } \ No newline at end of file diff --git a/src/audio/AudioPlayer.java b/src/audio/AudioPlayer.java index b7f1db7c..27379a75 100644 --- a/src/audio/AudioPlayer.java +++ b/src/audio/AudioPlayer.java @@ -2,30 +2,27 @@ package audio; import com.xtaudio.xt.*; import shapes.Shape; -import shapes.Shapes; import shapes.Vector2; import java.util.ArrayList; import java.util.List; public class AudioPlayer extends Thread { - private static double[] phases = new double[2]; private static XtFormat FORMAT; - private static List shapes = new ArrayList<>(); private static List> frames = new ArrayList<>(); private static int currentFrame = 0; private static int currentShape = 0; private static long timeOfLastFrame; private static int audioFramesDrawn = 0; - private static double TRANSLATE_SPEED = 0; - private static Vector2 TRANSLATE_VECTOR; - private static final int TRANSLATE_PHASE_INDEX = 0; - private static double ROTATE_SPEED = 0; - private static final int ROTATE_PHASE_INDEX = 1; - private static double SCALE = 1; - private static double WEIGHT = 100; + private double translateSpeed = 0; + private Vector2 translateVector = new Vector2(); + private Phase translatePhase = new Phase(); + private double rotateSpeed = 0; + private Phase rotatePhase = new Phase(); + private double scale = 1; + private double weight = 100; private volatile boolean stopped; @@ -35,12 +32,12 @@ public class AudioPlayer extends Thread { AudioPlayer.timeOfLastFrame = System.currentTimeMillis(); } - static void render(XtStream stream, Object input, Object output, int audioFrames, + private void render(XtStream stream, Object input, Object output, int audioFrames, double time, long position, boolean timeValid, long error, Object user) { for (int f = 0; f < audioFrames; f++) { Shape shape = getCurrentShape(); - shape = shape.setWeight(WEIGHT); + shape = shape.setWeight(weight); shape = scale(shape); shape = rotate(shape, FORMAT.mix.rate); shape = translate(shape, FORMAT.mix.rate); @@ -68,74 +65,62 @@ public class AudioPlayer extends Thread { } } - private static Shape rotate(Shape shape, double sampleRate) { - if (ROTATE_SPEED != 0) { + private Shape rotate(Shape shape, double sampleRate) { + if (rotateSpeed != 0) { shape = shape.rotate( - nextTheta(sampleRate, ROTATE_SPEED, TRANSLATE_PHASE_INDEX) + nextTheta(sampleRate, rotateSpeed, translatePhase) ); } return shape; } - private static Shape translate(Shape shape, double sampleRate) { - if (TRANSLATE_SPEED != 0 && !TRANSLATE_VECTOR.equals(new Vector2())) { - return shape.translate(TRANSLATE_VECTOR.scale( - Math.sin(nextTheta(sampleRate, TRANSLATE_SPEED, ROTATE_PHASE_INDEX)) + private Shape translate(Shape shape, double sampleRate) { + if (translateSpeed != 0 && !translateVector.equals(new Vector2())) { + return shape.translate(translateVector.scale( + Math.sin(nextTheta(sampleRate, translateSpeed, rotatePhase)) )); } return shape; } - static double nextTheta(double sampleRate, double frequency, int phaseIndex) { - phases[phaseIndex] += frequency / sampleRate; + private double nextTheta(double sampleRate, double frequency, Phase phase) { + phase.value += frequency / sampleRate; - if (phases[phaseIndex] >= 1.0) { - phases[phaseIndex] = -1.0; + if (phase.value >= 1.0) { + phase.value = -1.0; } - return phases[phaseIndex] * Math.PI; + return phase.value * Math.PI; } - private static Shape scale(Shape shape) { - if (SCALE != 1) { - return shape.scale(SCALE); + private Shape scale(Shape shape) { + if (scale != 1) { + return shape.scale(scale); } return shape; } - public static void setRotateSpeed(double speed) { - AudioPlayer.ROTATE_SPEED = speed; + public void setRotateSpeed(double speed) { + this.rotateSpeed = speed; } - public static void setTranslation(double speed, Vector2 translation) { - AudioPlayer.TRANSLATE_SPEED = speed; - AudioPlayer.TRANSLATE_VECTOR = translation; + public void setTranslation(double speed, Vector2 translation) { + this.translateSpeed = speed; + this.translateVector = translation; } - public static void setScale(double scale) { - AudioPlayer.SCALE = scale; + public void setScale(double scale) { + this.scale = scale; } - public static void addShape(Shape shape) { - shapes.add(shape); + public void setWeight(double weight) { + this.weight = weight; } - public static void addShapes(List newShapes) { - shapes.addAll(newShapes); - } - - public static void updateFrame(List frame) { - currentShape = 0; - shapes = new ArrayList<>(); - shapes.addAll(frame); - // Arbitrary function for changing weights based on frame draw-time. - AudioPlayer.WEIGHT = 200 * Math.exp(-0.017 * Shapes.totalLength(frame)); - } - - private static Shape getCurrentShape() { + private Shape getCurrentShape() { if (frames.size() == 0 || frames.get(currentFrame).size() == 0) { return new Vector2(0, 0); } @@ -152,7 +137,7 @@ public class AudioPlayer extends Thread { XtBuffer buffer = device.getBuffer(FORMAT); try (XtStream stream = device.openStream(FORMAT, true, false, - buffer.current, AudioPlayer::render, null, null)) { + buffer.current, this::render, null, null)) { stream.start(); while (!stopped) { Thread.onSpinWait(); @@ -167,4 +152,9 @@ public class AudioPlayer extends Thread { public void stopPlaying() { stopped = true; } -} \ No newline at end of file + + private static final class Phase { + private double value = 0; + } +} + diff --git a/src/engine/WorldObject.java b/src/engine/WorldObject.java index 90e2a25c..95ac9e1d 100644 --- a/src/engine/WorldObject.java +++ b/src/engine/WorldObject.java @@ -14,6 +14,15 @@ public class WorldObject { private Vector3 position; private Vector3 rotation; + public WorldObject(String filename) { + this.vertices = new ArrayList<>(); + this.edgeData = new ArrayList<>(); + this.position = new Vector3(); + this.rotation = new Vector3(); + + loadFromFile(filename); + } + public WorldObject(String filename, Vector3 position, Vector3 rotation) { this.vertices = new ArrayList<>(); this.edgeData = new ArrayList<>(); @@ -80,18 +89,6 @@ public class WorldObject { } public WorldObject clone() { - List newVertices = new ArrayList<>(); - - for (Vector3 vertex : vertices) { - newVertices.add(vertex.clone()); - } - - List newEdgeData = new ArrayList<>(); - - for (int edge : edgeData) { - newEdgeData.add(edge); - } - - return new WorldObject(newVertices, newEdgeData, position.clone(), rotation.clone()); + return new WorldObject(new ArrayList<>(vertices), new ArrayList<>(edgeData), position, rotation); } }