kopia lustrzana https://github.com/jameshball/osci-render
Remove MovableRenderer and add support for renderer effects
rodzic
809a2a229f
commit
6c42c62e43
4
pom.xml
4
pom.xml
|
@ -6,14 +6,14 @@
|
|||
|
||||
<groupId>sh.ball</groupId>
|
||||
<artifactId>osci-render</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.1.0</version>
|
||||
|
||||
<name>osci-render</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.release>15</maven.compiler.release>
|
||||
<javafx.version>15.0.1</javafx.version>
|
||||
<javafx.version>16</javafx.version>
|
||||
<project.modulePath>${project.build.directory}\modules</project.modulePath>
|
||||
<appModule>oscirender</appModule>
|
||||
<appMainClass>sh.ball.gui.Gui</appMainClass>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
package sh.ball;
|
||||
|
||||
public interface MovableRenderer<S, T> extends Renderer<S> {
|
||||
|
||||
void setRotationSpeed(double speed);
|
||||
|
||||
void setTranslation(T translation);
|
||||
|
||||
void setTranslationSpeed(double speed);
|
||||
|
||||
void setScale(double scale);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package sh.ball;
|
||||
|
||||
public interface Renderer<T> extends Runnable {
|
||||
|
||||
void stop();
|
||||
|
||||
void setQuality(double quality);
|
||||
|
||||
void addFrame(T frame);
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
import sh.ball.MovableRenderer;
|
||||
import xt.audio.Enums.XtSample;
|
||||
import xt.audio.Enums.XtSetup;
|
||||
import xt.audio.Enums.XtSystem;
|
||||
|
@ -18,6 +17,9 @@ import xt.audio.XtSafeBuffer;
|
|||
import xt.audio.XtService;
|
||||
import xt.audio.XtStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
|
@ -26,7 +28,7 @@ import sh.ball.shapes.Vector2;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class AudioPlayer implements MovableRenderer<List<Shape>, Vector2> {
|
||||
public class AudioPlayer implements Renderer<List<Shape>> {
|
||||
|
||||
private static final int SAMPLE_RATE = 192000;
|
||||
private static final int BUFFER_SIZE = 20;
|
||||
|
@ -36,6 +38,7 @@ public class AudioPlayer implements MovableRenderer<List<Shape>, Vector2> {
|
|||
private final XtFormat FORMAT = new XtFormat(MIX, CHANNELS);
|
||||
private final BlockingQueue<List<Shape>> frameQueue = new ArrayBlockingQueue<>(BUFFER_SIZE);
|
||||
|
||||
private Map<Object, Effect> effects = new HashMap<>();
|
||||
private List<Shape> frame;
|
||||
private int currentShape = 0;
|
||||
private int audioFramesDrawn = 0;
|
||||
|
@ -76,7 +79,7 @@ public class AudioPlayer implements MovableRenderer<List<Shape>, Vector2> {
|
|||
|
||||
double totalAudioFrames = shape.getWeight() * shape.getLength();
|
||||
double drawingProgress = totalAudioFrames == 0 ? 1 : audioFramesDrawn / totalAudioFrames;
|
||||
Vector2 nextVector = shape.nextVector(drawingProgress);
|
||||
Vector2 nextVector = applyEffects(f, shape.nextVector(drawingProgress));
|
||||
|
||||
output[f * FORMAT.channels.outputs] = (float) nextVector.getX();
|
||||
output[f * FORMAT.channels.outputs + 1] = (float) nextVector.getY();
|
||||
|
@ -97,6 +100,13 @@ public class AudioPlayer implements MovableRenderer<List<Shape>, Vector2> {
|
|||
return 0;
|
||||
}
|
||||
|
||||
private Vector2 applyEffects(int frame, Vector2 vector) {
|
||||
for (Effect effect : effects.values()) {
|
||||
vector = effect.apply(frame, vector);
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
||||
private Shape rotate(Shape shape, double sampleRate) {
|
||||
if (rotateSpeed != 0) {
|
||||
shape = shape.rotate(
|
||||
|
@ -135,22 +145,18 @@ public class AudioPlayer implements MovableRenderer<List<Shape>, Vector2> {
|
|||
return shape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotationSpeed(double speed) {
|
||||
this.rotateSpeed = speed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTranslation(Vector2 translation) {
|
||||
this.translateVector = translation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTranslationSpeed(double speed) {
|
||||
translateSpeed = speed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScale(double scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
@ -218,6 +224,16 @@ public class AudioPlayer implements MovableRenderer<List<Shape>, Vector2> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEffect(Object identifier, Effect effect) {
|
||||
effects.put(identifier, effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEffect(Object identifier) {
|
||||
effects.remove(identifier);
|
||||
}
|
||||
|
||||
private static final class Phase {
|
||||
|
||||
private double value = 0;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
import sh.ball.shapes.Vector2;
|
||||
|
||||
public interface Effect {
|
||||
Vector2 apply(int count, Vector2 vector);
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.Renderer;
|
||||
|
||||
public class FrameProducer<T> implements Runnable {
|
||||
|
||||
private final Renderer<T> renderer;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package sh.ball;
|
||||
package sh.ball.audio;
|
||||
|
||||
public interface FrameSet<T> {
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
public interface Renderer<T> extends Runnable {
|
||||
|
||||
void stop();
|
||||
|
||||
void setQuality(double quality);
|
||||
|
||||
void addFrame(T frame);
|
||||
|
||||
void addEffect(Object identifier, Effect effect);
|
||||
|
||||
void removeEffect(Object identifier);
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package sh.ball.gui;
|
||||
|
||||
import sh.ball.MovableRenderer;
|
||||
import javafx.scene.control.*;
|
||||
import sh.ball.audio.AudioPlayer;
|
||||
import sh.ball.audio.Effect;
|
||||
import sh.ball.audio.FrameProducer;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -17,11 +18,6 @@ import java.util.concurrent.Executors;
|
|||
import javafx.beans.InvalidationListener;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Slider;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
|
@ -40,7 +36,8 @@ public class Controller implements Initializable {
|
|||
private static final InputStream DEFAULT_OBJ = Controller.class.getResourceAsStream("/models/cube.obj");
|
||||
|
||||
private final FileChooser fileChooser = new FileChooser();
|
||||
private final MovableRenderer<List<Shape>, Vector2> renderer = new AudioPlayer();
|
||||
// TODO: Reduce coupling on AudioPlayer
|
||||
private final AudioPlayer renderer = new AudioPlayer();
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private FrameProducer<List<Shape>> producer = new FrameProducer<>(
|
||||
|
@ -86,6 +83,8 @@ public class Controller implements Initializable {
|
|||
private TextField cameraYTextField;
|
||||
@FXML
|
||||
private TextField cameraZTextField;
|
||||
@FXML
|
||||
private CheckBox vectorCancellingCheckBox;
|
||||
|
||||
public Controller() throws IOException {
|
||||
}
|
||||
|
@ -135,6 +134,11 @@ public class Controller implements Initializable {
|
|||
cameraYTextField.textProperty().addListener(cameraPosUpdate);
|
||||
cameraZTextField.textProperty().addListener(cameraPosUpdate);
|
||||
|
||||
vectorCancellingCheckBox.selectedProperty().addListener((o, old, checked) ->
|
||||
updateEffect(EffectType.VECTOR_CANCELLING, checked,
|
||||
((count, v) -> count % 2 == 0 ? v.scale(-1) : v))
|
||||
);
|
||||
|
||||
chooseFileButton.setOnAction(e -> {
|
||||
File file = fileChooser.showOpenDialog(stage);
|
||||
if (file != null) {
|
||||
|
@ -158,6 +162,14 @@ public class Controller implements Initializable {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateEffect(EffectType type, boolean checked, Effect effect) {
|
||||
if (checked) {
|
||||
renderer.addEffect(type, effect);
|
||||
} else {
|
||||
renderer.removeEffect(type);
|
||||
}
|
||||
}
|
||||
|
||||
private void chooseFile(File file) {
|
||||
try {
|
||||
producer.stop();
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package sh.ball.gui;
|
||||
|
||||
enum EffectType {
|
||||
VECTOR_CANCELLING
|
||||
}
|
|
@ -22,6 +22,7 @@ public class Gui extends Application {
|
|||
stage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/icons/icon.png"))));
|
||||
stage.setTitle("osci-render");
|
||||
stage.setScene(new Scene(root));
|
||||
stage.setResizable(false);
|
||||
|
||||
controller.setStage(stage);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package sh.ball.parser;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.audio.FrameSet;
|
||||
import sh.ball.parser.obj.ObjParser;
|
||||
import sh.ball.parser.svg.SvgParser;
|
||||
import sh.ball.parser.txt.TextParser;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package sh.ball.parser.obj;
|
||||
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.audio.FrameSet;
|
||||
import sh.ball.engine.Camera;
|
||||
import sh.ball.engine.Vector3;
|
||||
import sh.ball.engine.WorldObject;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package sh.ball.parser.obj;
|
||||
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.audio.FrameSet;
|
||||
import sh.ball.engine.Camera;
|
||||
import sh.ball.engine.Vector3;
|
||||
import sh.ball.engine.WorldObject;
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.unbescape.html.HtmlEscape;
|
|||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.SAXException;
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.audio.FrameSet;
|
||||
import sh.ball.parser.FileParser;
|
||||
import sh.ball.shapes.ShapeFrameSet;
|
||||
import sh.ball.shapes.Shape;
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.util.stream.Collectors;
|
|||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.audio.FrameSet;
|
||||
import sh.ball.parser.FileParser;
|
||||
import sh.ball.shapes.ShapeFrameSet;
|
||||
import sh.ball.parser.svg.SvgParser;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package sh.ball.shapes;
|
||||
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.audio.FrameSet;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.PathIterator;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package sh.ball.shapes;
|
||||
|
||||
import sh.ball.FrameSet;
|
||||
import sh.ball.shapes.Shape;
|
||||
import sh.ball.audio.FrameSet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.Slider?>
|
||||
<?import javafx.scene.control.SplitPane?>
|
||||
|
@ -11,17 +12,17 @@
|
|||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
|
||||
<GridPane alignment="center" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sh.ball.gui.Controller">
|
||||
<GridPane alignment="center" hgap="10" prefWidth="400.0" vgap="10" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sh.ball.gui.Controller">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints />
|
||||
</rowConstraints>
|
||||
<AnchorPane prefHeight="279.0" prefWidth="400.0">
|
||||
<AnchorPane prefHeight="602.0" prefWidth="400.0">
|
||||
<Button fx:id="chooseFileButton" layoutX="8.0" layoutY="15.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="119.0" text="Choose File" />
|
||||
<SplitPane dividerPositions="0.4723618090452261" layoutX="8.0" layoutY="56.0" orientation="VERTICAL" prefHeight="371.0" prefWidth="386.0">
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="0.0" prefWidth="385.0">
|
||||
<SplitPane dividerPositions="0.3406015037593984, 0.669548872180451" layoutX="8.0" layoutY="63.0" orientation="VERTICAL" prefHeight="533.0" prefWidth="386.0">
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="271.0" prefWidth="385.0">
|
||||
<Slider fx:id="rotateSpeedSlider" layoutX="116.0" layoutY="79.0" max="10.0" prefHeight="14.0" prefWidth="198.0" />
|
||||
<Label layoutX="37.0" layoutY="77.0" text="Rotate speed" />
|
||||
<Label fx:id="rotateSpeedLabel" layoutX="316.0" layoutY="77.0" text="0" />
|
||||
|
@ -40,8 +41,17 @@
|
|||
<Slider fx:id="weightSlider" layoutX="116.0" layoutY="52.0" max="1000.0" prefHeight="14.0" prefWidth="198.0" value="100.0" />
|
||||
<Label fx:id="weightLabel" layoutX="316.0" layoutY="51.0" text="100" />
|
||||
</AnchorPane>
|
||||
<TitledPane fx:id="objTitledPane" animated="false" collapsible="false" text="3D .obj file settings">
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||
<TitledPane animated="false" collapsible="false" prefHeight="169.0" prefWidth="385.0" text="Effects" SplitPane.resizableWithParent="false">
|
||||
<content>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||
<children>
|
||||
<CheckBox fx:id="vectorCancellingCheckBox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="Vector cancelling" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</content>
|
||||
</TitledPane>
|
||||
<TitledPane fx:id="objTitledPane" animated="false" collapsible="false" prefHeight="186.0" prefWidth="385.0" text="3D .obj file settings" SplitPane.resizableWithParent="false">
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="96.0" prefWidth="382.0">
|
||||
<Slider fx:id="focalLengthSlider" blockIncrement="2.0" layoutX="116.0" layoutY="15.0" max="2.0" min="1.0E-5" prefHeight="14.0" prefWidth="198.0" value="1.0" />
|
||||
<Label layoutX="43.0" layoutY="14.0" text="Focal length" />
|
||||
<Label fx:id="focalLengthLabel" layoutX="316.0" layoutY="14.0" text="1" />
|
||||
|
@ -55,6 +65,6 @@
|
|||
</AnchorPane>
|
||||
</TitledPane>
|
||||
</SplitPane>
|
||||
<Label fx:id="fileLabel" layoutX="134.0" layoutY="20.0" />
|
||||
<Label fx:id="fileLabel" layoutX="134.0" layoutY="20.0" maxWidth="250.0" />
|
||||
</AnchorPane>
|
||||
</GridPane>
|
||||
|
|
Ładowanie…
Reference in New Issue