kopia lustrzana https://github.com/jameshball/osci-render
Add bit crush effect and decrease latency of render update
rodzic
2172478acf
commit
dbd55e96ea
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<groupId>sh.ball</groupId>
|
<groupId>sh.ball</groupId>
|
||||||
<artifactId>osci-render</artifactId>
|
<artifactId>osci-render</artifactId>
|
||||||
<version>1.1.0</version>
|
<version>1.1.1</version>
|
||||||
|
|
||||||
<name>osci-render</name>
|
<name>osci-render</name>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package sh.ball.audio;
|
package sh.ball.audio;
|
||||||
|
|
||||||
|
import sh.ball.audio.effect.Effect;
|
||||||
import xt.audio.Enums.XtSample;
|
import xt.audio.Enums.XtSample;
|
||||||
import xt.audio.Enums.XtSetup;
|
import xt.audio.Enums.XtSetup;
|
||||||
import xt.audio.Enums.XtSystem;
|
import xt.audio.Enums.XtSystem;
|
||||||
|
@ -17,7 +18,6 @@ import xt.audio.XtSafeBuffer;
|
||||||
import xt.audio.XtService;
|
import xt.audio.XtService;
|
||||||
import xt.audio.XtStream;
|
import xt.audio.XtStream;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
@ -224,6 +224,11 @@ public class AudioPlayer implements Renderer<List<Shape>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flushFrames() {
|
||||||
|
frameQueue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addEffect(Object identifier, Effect effect) {
|
public void addEffect(Object identifier, Effect effect) {
|
||||||
effects.put(identifier, effect);
|
effects.put(identifier, effect);
|
||||||
|
|
|
@ -24,7 +24,8 @@ public class FrameProducer<T> implements Runnable {
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFrameSettings(Object settings) {
|
public Object setFrameSettings(Object settings) {
|
||||||
frames.setFrameSettings(settings);
|
renderer.flushFrames();
|
||||||
|
return frames.setFrameSettings(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,5 @@ public interface FrameSet<T> {
|
||||||
|
|
||||||
T next();
|
T next();
|
||||||
|
|
||||||
void setFrameSettings(Object settings);
|
Object setFrameSettings(Object settings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package sh.ball.audio;
|
package sh.ball.audio;
|
||||||
|
|
||||||
|
import sh.ball.audio.effect.Effect;
|
||||||
|
|
||||||
public interface Renderer<T> extends Runnable {
|
public interface Renderer<T> extends Runnable {
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
@ -8,6 +10,8 @@ public interface Renderer<T> extends Runnable {
|
||||||
|
|
||||||
void addFrame(T frame);
|
void addFrame(T frame);
|
||||||
|
|
||||||
|
void flushFrames();
|
||||||
|
|
||||||
void addEffect(Object identifier, Effect effect);
|
void addEffect(Object identifier, Effect effect);
|
||||||
|
|
||||||
void removeEffect(Object identifier);
|
void removeEffect(Object identifier);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package sh.ball.audio;
|
package sh.ball.audio.effect;
|
||||||
|
|
||||||
import sh.ball.shapes.Vector2;
|
import sh.ball.shapes.Vector2;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package sh.ball.audio.effect;
|
||||||
|
|
||||||
|
public enum EffectType {
|
||||||
|
VECTOR_CANCELLING,
|
||||||
|
BIT_CRUSH
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package sh.ball.audio.effect;
|
||||||
|
|
||||||
|
import sh.ball.shapes.Vector2;
|
||||||
|
|
||||||
|
public class EventFactory {
|
||||||
|
public static Effect vectorCancelling(int frequency) {
|
||||||
|
return (count, v) -> count % frequency == 0 ? v.scale(-1) : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Effect bitCrush(double value) {
|
||||||
|
return (count, v) -> {
|
||||||
|
double x = v.getX();
|
||||||
|
double y = v.getY();
|
||||||
|
return new Vector2(round(x, value), round(y, value));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double round(double value, double places) {
|
||||||
|
if (places < 0) throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
long factor = (long) Math.pow(10, places);
|
||||||
|
value = value * factor;
|
||||||
|
long tmp = Math.round(value);
|
||||||
|
return (double) tmp / factor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,15 @@ package sh.ball.gui;
|
||||||
|
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import sh.ball.audio.AudioPlayer;
|
import sh.ball.audio.AudioPlayer;
|
||||||
import sh.ball.audio.Effect;
|
import sh.ball.audio.effect.Effect;
|
||||||
import sh.ball.audio.FrameProducer;
|
import sh.ball.audio.FrameProducer;
|
||||||
|
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.EventListener;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
@ -21,9 +23,13 @@ import javafx.fxml.Initializable;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
import sh.ball.audio.effect.EffectType;
|
||||||
|
import sh.ball.audio.effect.EventFactory;
|
||||||
import sh.ball.engine.Vector3;
|
import sh.ball.engine.Vector3;
|
||||||
import sh.ball.parser.obj.ObjFrameSettings;
|
import sh.ball.parser.obj.ObjFrameSettings;
|
||||||
import sh.ball.parser.obj.ObjParser;
|
import sh.ball.parser.obj.ObjParser;
|
||||||
|
@ -87,6 +93,10 @@ public class Controller implements Initializable {
|
||||||
private CheckBox vectorCancellingCheckBox;
|
private CheckBox vectorCancellingCheckBox;
|
||||||
@FXML
|
@FXML
|
||||||
private Slider vectorCancellingSlider;
|
private Slider vectorCancellingSlider;
|
||||||
|
@FXML
|
||||||
|
private CheckBox bitCrushCheckBox;
|
||||||
|
@FXML
|
||||||
|
private Slider bitCrushSlider;
|
||||||
|
|
||||||
public Controller() throws IOException {
|
public Controller() throws IOException {
|
||||||
}
|
}
|
||||||
|
@ -111,7 +121,9 @@ public class Controller implements Initializable {
|
||||||
private void initializeEffectTypes() {
|
private void initializeEffectTypes() {
|
||||||
effectTypes = Map.of(
|
effectTypes = Map.of(
|
||||||
EffectType.VECTOR_CANCELLING,
|
EffectType.VECTOR_CANCELLING,
|
||||||
vectorCancellingSlider
|
vectorCancellingSlider,
|
||||||
|
EffectType.BIT_CRUSH,
|
||||||
|
bitCrushSlider
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,16 +152,25 @@ public class Controller implements Initializable {
|
||||||
tryParse(cameraXTextField.getText()),
|
tryParse(cameraXTextField.getText()),
|
||||||
tryParse(cameraYTextField.getText()),
|
tryParse(cameraYTextField.getText()),
|
||||||
tryParse(cameraZTextField.getText())
|
tryParse(cameraZTextField.getText())
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
cameraXTextField.textProperty().addListener(cameraPosUpdate);
|
cameraXTextField.textProperty().addListener(cameraPosUpdate);
|
||||||
cameraYTextField.textProperty().addListener(cameraPosUpdate);
|
cameraYTextField.textProperty().addListener(cameraPosUpdate);
|
||||||
cameraZTextField.textProperty().addListener(cameraPosUpdate);
|
cameraZTextField.textProperty().addListener(cameraPosUpdate);
|
||||||
|
|
||||||
vectorCancellingCheckBox.selectedProperty().addListener((o, old, checked) ->
|
InvalidationListener vectorCancellingListener = e ->
|
||||||
updateEffect(EffectType.VECTOR_CANCELLING, checked,
|
updateEffect(EffectType.VECTOR_CANCELLING, vectorCancellingCheckBox.isSelected(),
|
||||||
((count, v) -> count % (int) vectorCancellingSlider.getValue() == 0 ? v.scale(-1) : v))
|
EventFactory.vectorCancelling((int) vectorCancellingSlider.getValue()));
|
||||||
);
|
InvalidationListener bitCrushListener = e ->
|
||||||
|
updateEffect(EffectType.BIT_CRUSH, bitCrushCheckBox.isSelected(),
|
||||||
|
EventFactory.bitCrush(bitCrushSlider.getValue()));
|
||||||
|
|
||||||
|
vectorCancellingSlider.valueProperty().addListener(vectorCancellingListener);
|
||||||
|
vectorCancellingCheckBox.selectedProperty().addListener(vectorCancellingListener);
|
||||||
|
|
||||||
|
bitCrushSlider.valueProperty().addListener(bitCrushListener);
|
||||||
|
bitCrushCheckBox.selectedProperty().addListener(bitCrushListener);
|
||||||
|
|
||||||
chooseFileButton.setOnAction(e -> {
|
chooseFileButton.setOnAction(e -> {
|
||||||
File file = fileChooser.showOpenDialog(stage);
|
File file = fileChooser.showOpenDialog(stage);
|
||||||
|
@ -163,7 +184,10 @@ public class Controller implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFocalLength(double focalLength) {
|
private void setFocalLength(double focalLength) {
|
||||||
producer.setFrameSettings(new ObjFrameSettings(focalLength));
|
Vector3 pos = (Vector3) producer.setFrameSettings(new ObjFrameSettings(focalLength));
|
||||||
|
cameraXTextField.setText(String.valueOf(pos.getX()));
|
||||||
|
cameraYTextField.setText(String.valueOf(pos.getY()));
|
||||||
|
cameraZTextField.setText(String.valueOf(pos.getZ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private double tryParse(String value) {
|
private double tryParse(String value) {
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package sh.ball.gui;
|
|
||||||
|
|
||||||
enum EffectType {
|
|
||||||
VECTOR_CANCELLING
|
|
||||||
}
|
|
|
@ -29,7 +29,7 @@ public class ObjFrameSet implements FrameSet<List<Shape>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFrameSettings(Object settings) {
|
public Object setFrameSettings(Object settings) {
|
||||||
if (settings instanceof ObjFrameSettings obj) {
|
if (settings instanceof ObjFrameSettings obj) {
|
||||||
Double focalLength = obj.focalLength();
|
Double focalLength = obj.focalLength();
|
||||||
Vector3 cameraPos = obj.cameraPos();
|
Vector3 cameraPos = obj.cameraPos();
|
||||||
|
@ -44,5 +44,7 @@ public class ObjFrameSet implements FrameSet<List<Shape>> {
|
||||||
camera.setPos(cameraPos);
|
camera.setPos(cameraPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return camera.getPos();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,9 @@ public abstract class Shape implements FrameSet<List<Shape>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFrameSettings(Object settings) {}
|
public Object setFrameSettings(Object settings) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/* SHAPE HELPER FUNCTIONS */
|
/* SHAPE HELPER FUNCTIONS */
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ public class ShapeFrameSet implements FrameSet<List<Shape>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFrameSettings(Object settings) {
|
public Object setFrameSettings(Object settings) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="271.0" prefWidth="385.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" />
|
<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 layoutX="37.0" layoutY="77.0" text="Rotate speed" />
|
||||||
<Label fx:id="rotateSpeedLabel" layoutX="316.0" layoutY="77.0" text="0" />
|
<Label fx:id="rotateSpeedLabel" layoutX="316.0" layoutY="77.0" maxWidth="40.0" text="0" />
|
||||||
<Slider fx:id="translationSpeedSlider" layoutX="116.0" layoutY="105.0" max="10.0" prefHeight="14.0" prefWidth="198.0" value="1.0" />
|
<Slider fx:id="translationSpeedSlider" layoutX="116.0" layoutY="105.0" max="10.0" prefHeight="14.0" prefWidth="198.0" value="1.0" />
|
||||||
<Label layoutX="14.0" layoutY="103.0" text="Translation speed" />
|
<Label layoutX="14.0" layoutY="103.0" text="Translation speed" />
|
||||||
<Label fx:id="translationSpeedLabel" layoutX="316.0" layoutY="103.0" text="1" />
|
<Label fx:id="translationSpeedLabel" layoutX="316.0" layoutY="103.0" maxWidth="40.0" text="1" />
|
||||||
<Slider fx:id="scaleSlider" layoutX="116.0" layoutY="130.0" max="10.0" prefHeight="14.0" prefWidth="198.0" value="1.0" />
|
<Slider fx:id="scaleSlider" layoutX="116.0" layoutY="130.0" max="10.0" prefHeight="14.0" prefWidth="198.0" value="1.0" />
|
||||||
<Label layoutX="80.0" layoutY="128.0" text="Scale" />
|
<Label layoutX="80.0" layoutY="128.0" text="Scale" />
|
||||||
<Label fx:id="scaleLabel" layoutX="316.0" layoutY="128.0" text="1" />
|
<Label fx:id="scaleLabel" layoutX="316.0" layoutY="128.0" maxWidth="40.0" text="1" />
|
||||||
<Label layoutX="70.0" layoutY="50.0" text="Weight" />
|
<Label layoutX="70.0" layoutY="50.0" text="Weight" />
|
||||||
<TextField fx:id="translationXTextField" layoutX="136.0" layoutY="13.0" prefHeight="26.0" prefWidth="70.0" text="0" />
|
<TextField fx:id="translationXTextField" layoutX="136.0" layoutY="13.0" prefHeight="26.0" prefWidth="70.0" text="0" />
|
||||||
<Label layoutX="51.0" layoutY="18.0" text="Translation" />
|
<Label layoutX="51.0" layoutY="18.0" text="Translation" />
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
<Label layoutX="217.0" layoutY="18.0" text="y :" />
|
<Label layoutX="217.0" layoutY="18.0" text="y :" />
|
||||||
<TextField fx:id="translationYTextField" layoutX="234.0" layoutY="13.0" prefHeight="26.0" prefWidth="70.0" text="0" />
|
<TextField fx:id="translationYTextField" layoutX="234.0" layoutY="13.0" prefHeight="26.0" prefWidth="70.0" text="0" />
|
||||||
<Slider fx:id="weightSlider" layoutX="116.0" layoutY="52.0" max="1000.0" prefHeight="14.0" prefWidth="198.0" value="100.0" />
|
<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" />
|
<Label fx:id="weightLabel" layoutX="316.0" layoutY="51.0" maxWidth="40.0" text="100" />
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
<TitledPane animated="false" collapsible="false" prefHeight="169.0" prefWidth="385.0" text="Effects" SplitPane.resizableWithParent="false">
|
<TitledPane animated="false" collapsible="false" prefHeight="169.0" prefWidth="385.0" text="Effects" SplitPane.resizableWithParent="false">
|
||||||
<content>
|
<content>
|
||||||
|
@ -47,6 +47,8 @@
|
||||||
<children>
|
<children>
|
||||||
<CheckBox fx:id="vectorCancellingCheckBox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="Vector cancelling" />
|
<CheckBox fx:id="vectorCancellingCheckBox" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="Vector cancelling" />
|
||||||
<Slider fx:id="vectorCancellingSlider" blockIncrement="1.0" disable="true" layoutX="141.0" layoutY="16.0" majorTickUnit="1.0" max="10.0" min="2.0" minorTickCount="0" prefHeight="33.0" prefWidth="198.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="2.0" />
|
<Slider fx:id="vectorCancellingSlider" blockIncrement="1.0" disable="true" layoutX="141.0" layoutY="16.0" majorTickUnit="1.0" max="10.0" min="2.0" minorTickCount="0" prefHeight="33.0" prefWidth="198.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="2.0" />
|
||||||
|
<CheckBox fx:id="bitCrushCheckBox" layoutX="14.0" layoutY="52.0" mnemonicParsing="false" text="Bit crush" />
|
||||||
|
<Slider fx:id="bitCrushSlider" blockIncrement="1.0" disable="true" layoutX="141.0" layoutY="55.0" majorTickUnit="0.5" max="3.0" minorTickCount="0" prefHeight="33.0" prefWidth="198.0" showTickLabels="true" showTickMarks="true" value="2.0" />
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</content>
|
</content>
|
||||||
|
@ -56,13 +58,13 @@
|
||||||
<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" />
|
<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 layoutX="43.0" layoutY="14.0" text="Focal length" />
|
||||||
<Label fx:id="focalLengthLabel" layoutX="316.0" layoutY="14.0" text="1" />
|
<Label fx:id="focalLengthLabel" layoutX="316.0" layoutY="14.0" text="1" />
|
||||||
<TextField fx:id="cameraXTextField" layoutX="134.0" layoutY="39.0" prefHeight="26.0" prefWidth="38.0" text="0" />
|
<TextField fx:id="cameraXTextField" layoutX="134.0" layoutY="39.0" prefHeight="26.0" prefWidth="58.0" text="0" />
|
||||||
<Label layoutX="44.0" layoutY="44.0" text="Camera pos" />
|
<Label layoutX="44.0" layoutY="44.0" text="Camera pos" />
|
||||||
<Label layoutX="118.0" layoutY="44.0" text="x :" />
|
<Label layoutX="118.0" layoutY="44.0" text="x :" />
|
||||||
<Label layoutX="180.0" layoutY="43.0" text="y :" />
|
<Label layoutX="199.0" layoutY="43.0" text="y :" />
|
||||||
<TextField fx:id="cameraYTextField" layoutX="199.0" layoutY="39.0" prefHeight="26.0" prefWidth="38.0" text="0" />
|
<TextField fx:id="cameraYTextField" layoutX="218.0" layoutY="39.0" prefHeight="26.0" prefWidth="58.0" text="0" />
|
||||||
<Label layoutX="244.0" layoutY="43.0" text="z :" />
|
<Label layoutX="283.0" layoutY="43.0" text="z :" />
|
||||||
<TextField fx:id="cameraZTextField" layoutX="263.0" layoutY="39.0" prefHeight="26.0" prefWidth="38.0" text="0" />
|
<TextField fx:id="cameraZTextField" layoutX="302.0" layoutY="39.0" prefHeight="26.0" prefWidth="58.0" text="0" />
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
|
|
Ładowanie…
Reference in New Issue