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>
|
||||
<artifactId>osci-render</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
|
||||
<name>osci-render</name>
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
import sh.ball.audio.effect.Effect;
|
||||
import xt.audio.Enums.XtSample;
|
||||
import xt.audio.Enums.XtSetup;
|
||||
import xt.audio.Enums.XtSystem;
|
||||
|
@ -17,7 +18,6 @@ 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;
|
||||
|
@ -224,6 +224,11 @@ public class AudioPlayer implements Renderer<List<Shape>> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushFrames() {
|
||||
frameQueue.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEffect(Object identifier, Effect effect) {
|
||||
effects.put(identifier, effect);
|
||||
|
|
|
@ -24,7 +24,8 @@ public class FrameProducer<T> implements Runnable {
|
|||
running = false;
|
||||
}
|
||||
|
||||
public void setFrameSettings(Object settings) {
|
||||
frames.setFrameSettings(settings);
|
||||
public Object setFrameSettings(Object settings) {
|
||||
renderer.flushFrames();
|
||||
return frames.setFrameSettings(settings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@ public interface FrameSet<T> {
|
|||
|
||||
T next();
|
||||
|
||||
void setFrameSettings(Object settings);
|
||||
Object setFrameSettings(Object settings);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
import sh.ball.audio.effect.Effect;
|
||||
|
||||
public interface Renderer<T> extends Runnable {
|
||||
|
||||
void stop();
|
||||
|
@ -8,6 +10,8 @@ public interface Renderer<T> extends Runnable {
|
|||
|
||||
void addFrame(T frame);
|
||||
|
||||
void flushFrames();
|
||||
|
||||
void addEffect(Object identifier, Effect effect);
|
||||
|
||||
void removeEffect(Object identifier);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package sh.ball.audio;
|
||||
package sh.ball.audio.effect;
|
||||
|
||||
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 sh.ball.audio.AudioPlayer;
|
||||
import sh.ball.audio.Effect;
|
||||
import sh.ball.audio.effect.Effect;
|
||||
import sh.ball.audio.FrameProducer;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
@ -21,9 +23,13 @@ import javafx.fxml.Initializable;
|
|||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
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.parser.obj.ObjFrameSettings;
|
||||
import sh.ball.parser.obj.ObjParser;
|
||||
|
@ -87,6 +93,10 @@ public class Controller implements Initializable {
|
|||
private CheckBox vectorCancellingCheckBox;
|
||||
@FXML
|
||||
private Slider vectorCancellingSlider;
|
||||
@FXML
|
||||
private CheckBox bitCrushCheckBox;
|
||||
@FXML
|
||||
private Slider bitCrushSlider;
|
||||
|
||||
public Controller() throws IOException {
|
||||
}
|
||||
|
@ -111,7 +121,9 @@ public class Controller implements Initializable {
|
|||
private void initializeEffectTypes() {
|
||||
effectTypes = Map.of(
|
||||
EffectType.VECTOR_CANCELLING,
|
||||
vectorCancellingSlider
|
||||
vectorCancellingSlider,
|
||||
EffectType.BIT_CRUSH,
|
||||
bitCrushSlider
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -140,16 +152,25 @@ public class Controller implements Initializable {
|
|||
tryParse(cameraXTextField.getText()),
|
||||
tryParse(cameraYTextField.getText()),
|
||||
tryParse(cameraZTextField.getText())
|
||||
)));
|
||||
)));
|
||||
|
||||
|
||||
cameraXTextField.textProperty().addListener(cameraPosUpdate);
|
||||
cameraYTextField.textProperty().addListener(cameraPosUpdate);
|
||||
cameraZTextField.textProperty().addListener(cameraPosUpdate);
|
||||
|
||||
vectorCancellingCheckBox.selectedProperty().addListener((o, old, checked) ->
|
||||
updateEffect(EffectType.VECTOR_CANCELLING, checked,
|
||||
((count, v) -> count % (int) vectorCancellingSlider.getValue() == 0 ? v.scale(-1) : v))
|
||||
);
|
||||
InvalidationListener vectorCancellingListener = e ->
|
||||
updateEffect(EffectType.VECTOR_CANCELLING, vectorCancellingCheckBox.isSelected(),
|
||||
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 -> {
|
||||
File file = fileChooser.showOpenDialog(stage);
|
||||
|
@ -163,7 +184,10 @@ public class Controller implements Initializable {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package sh.ball.gui;
|
||||
|
||||
enum EffectType {
|
||||
VECTOR_CANCELLING
|
||||
}
|
|
@ -29,7 +29,7 @@ public class ObjFrameSet implements FrameSet<List<Shape>> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setFrameSettings(Object settings) {
|
||||
public Object setFrameSettings(Object settings) {
|
||||
if (settings instanceof ObjFrameSettings obj) {
|
||||
Double focalLength = obj.focalLength();
|
||||
Vector3 cameraPos = obj.cameraPos();
|
||||
|
@ -44,5 +44,7 @@ public class ObjFrameSet implements FrameSet<List<Shape>> {
|
|||
camera.setPos(cameraPos);
|
||||
}
|
||||
}
|
||||
|
||||
return camera.getPos();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,9 @@ public abstract class Shape implements FrameSet<List<Shape>> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setFrameSettings(Object settings) {}
|
||||
public Object setFrameSettings(Object settings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* SHAPE HELPER FUNCTIONS */
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ public class ShapeFrameSet implements FrameSet<List<Shape>> {
|
|||
}
|
||||
|
||||
@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">
|
||||
<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" />
|
||||
<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" />
|
||||
<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" />
|
||||
<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" />
|
||||
<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" />
|
||||
|
@ -39,7 +39,7 @@
|
|||
<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" />
|
||||
<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>
|
||||
<TitledPane animated="false" collapsible="false" prefHeight="169.0" prefWidth="385.0" text="Effects" SplitPane.resizableWithParent="false">
|
||||
<content>
|
||||
|
@ -47,6 +47,8 @@
|
|||
<children>
|
||||
<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" />
|
||||
<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>
|
||||
</AnchorPane>
|
||||
</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" />
|
||||
<Label layoutX="43.0" layoutY="14.0" text="Focal length" />
|
||||
<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="118.0" layoutY="44.0" text="x :" />
|
||||
<Label layoutX="180.0" layoutY="43.0" text="y :" />
|
||||
<TextField fx:id="cameraYTextField" layoutX="199.0" layoutY="39.0" prefHeight="26.0" prefWidth="38.0" text="0" />
|
||||
<Label layoutX="244.0" layoutY="43.0" text="z :" />
|
||||
<TextField fx:id="cameraZTextField" layoutX="263.0" layoutY="39.0" prefHeight="26.0" prefWidth="38.0" text="0" />
|
||||
<Label layoutX="199.0" layoutY="43.0" text="y :" />
|
||||
<TextField fx:id="cameraYTextField" layoutX="218.0" layoutY="39.0" prefHeight="26.0" prefWidth="58.0" text="0" />
|
||||
<Label layoutX="283.0" layoutY="43.0" text="z :" />
|
||||
<TextField fx:id="cameraZTextField" layoutX="302.0" layoutY="39.0" prefHeight="26.0" prefWidth="58.0" text="0" />
|
||||
</AnchorPane>
|
||||
</TitledPane>
|
||||
</SplitPane>
|
||||
|
|
Ładowanie…
Reference in New Issue