Initial commit
Diff
.DS_Store | 0
.classpath | 10 ++++++++++
.gitignore | 1 +
.project | 17 +++++++++++++++++
.settings/org.eclipse.core.resources.prefs | 2 ++
.settings/org.eclipse.jdt.core.prefs | 14 ++++++++++++++
src/.DS_Store | 0
src/module-info.java | 3 +++
src/absmaths/AbsMaths.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/absmaths/Complex.java | 23 +++++++++++++++++++++++
src/absmaths/Matrix.java | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/absmaths/package-info.java | 1 +
src/eyecandy/CubeRotator.java | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eyecandy/Drawable.java | 8 ++++++++
src/eyecandy/Mandelbrot.java | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eyecandy/Modulo.java | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eyecandy/Sorter.java | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/eyecandy/StackableBackground.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/eyecandy/ball.gif | 0
src/eyecandy/fontsheet.gif | 0
src/main/DemoPanel.java | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/KeyHandler.java | 35 +++++++++++++++++++++++++++++++++++
src/main/Main.java | 27 +++++++++++++++++++++++++++
23 files changed, 813 insertions(+)
Binary files /dev/null and a/.DS_Store differ
@@ -1,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -1,0 +1,1 @@
bin/
@@ -1,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Demo</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -1,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
@@ -1,0 +1,14 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=17
Binary files /dev/null and a/src/.DS_Store differ
@@ -1,0 +1,3 @@
module Demo {
requires java.desktop;
}
@@ -1,0 +1,51 @@
package absmaths;
public class AbsMaths {
public static int[][] newTimesTable (int width, int height) {
int[][] arr = new int[width][height];
for (int x=0; x<width; x++) {
for (int y=0; y<height; y++) {
arr[x][y] = x * y;
}
}
return arr;
}
public static int[] sanitizeToBounds (int[] array, int floor, int ceiling) {
int[] result = new int[array.length];
for (int i = 0; i < result.length; i++) {
result[i] = Math.min(ceiling, Math.max(floor, array[i]));
}
return result;
}
public static float[] sanitizeToBounds (float[] array, float floor, float ceiling) {
float[] result = new float[array.length];
for (int i = 0; i < result.length; i++) {
result[i] = Math.min(ceiling, Math.max(floor, array[i]));
}
return result;
}
public static double[] sanitizeToBounds (double[] array, double floor, double ceiling) {
double[] result = new double[array.length];
for (int i = 0; i < result.length; i++) {
result[i] = Math.min(ceiling, Math.max(floor, array[i]));
}
return result;
}
public static int sanitizeToBounds (int sanitizand, int floor, int ceiling) {
return Math.min(ceiling, Math.max(floor, sanitizand));
}
public static float sanitizeToBounds (float sanitizand, float floor, float ceiling) {
return Math.min(ceiling, Math.max(floor, sanitizand));
}
public static double sanitizeToBounds (double sanitizand, double floor, double ceiling) {
return Math.min(ceiling, Math.max(floor, sanitizand));
}
}
@@ -1,0 +1,23 @@
package absmaths;
public class Complex {
public double i;
public double r;
public Complex(double r, double i) {
this.i = i;
this.r = r;
}
public Complex square() {
this.r = this.r * this.r - this.i * this.i;
this.i = 0;
return this;
}
public Complex add(Complex x) {
this.r += x.r;
this.i += x.i;
return this;
}
}
@@ -1,0 +1,66 @@
package absmaths;
import java.util.Arrays;
public class Matrix {
double[][] matrix;
public double[][] getMatrix() {
return matrix;
}
public void setMatrix(double[][] matrix) {
this.matrix = matrix;
}
public Matrix(double[][] matrix) {
this.setMatrix(matrix);
}
public Matrix(int rows, int columns) {
this.setMatrix(new double[rows][columns]);
}
public Matrix getProduct(Matrix m) {
double[][] multiplicand = m.getMatrix();
double[][] result = new double[matrix.length][multiplicand[0].length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < multiplicand[0].length; j++) {
result[i][j] = vectorDotProduct(result[i], getColumnAsArray(j, multiplicand));
}
}
return new Matrix(result);
}
public double[] getColumnAsArray(int indicand) {
return getColumnAsArray(indicand, this.matrix);
}
public static double[] getColumnAsArray(int indicand, Matrix x) {
return getColumnAsArray(indicand, x.getMatrix());
}
public static double[] getColumnAsArray(int indicand, double[][] x) {
double[] result = new double[x.length];
for (int i = 0; i < result.length; i++) {
result[i] = x[i][indicand];
}
return result;
}
public static double vectorDotProduct(double[] x, double[] y) {
double product = 0;
if (x.length == y.length) {
for (int i = 0; i < x.length; i++) {
product += x[i] * y[i];
}
} else {
System.out.println("Dot product length wrong!");
}
return product;
}
public String toString() {
return Arrays.deepToString(matrix);
}
}
@@ -1,0 +1,1 @@
package absmaths;
@@ -1,0 +1,118 @@
package eyecandy;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import absmaths.Matrix;
public class CubeRotator implements Drawable {
final int scaleFactor = 50;
final int width = 320;
final int height = 200;
final int offsetWidth = width / 2;
final int offsetHeight = height / 2;
enum Axis {
X,
Y,
Z
}
final Matrix[] verticesPrimary = new Matrix[] {
new Matrix(new double[][] {{-1}, {-1}, {1}}),
new Matrix(new double[][] {{1}, {-1}, {1}}),
new Matrix(new double[][] {{1}, {1}, {1}}),
new Matrix(new double[][] {{-1}, {1}, {1}}),
new Matrix(new double[][] {{-1}, {-1}, {-1}}),
new Matrix(new double[][] {{1}, {-1}, {-1}}),
new Matrix(new double[][] {{1}, {1}, {-1}}),
new Matrix(new double[][] {{-1}, {1}, {-1}})
};
Matrix[] vertices = verticesPrimary.clone();
Matrix[] verticesProjected = new Matrix[8];
Matrix projectionMatrix = new Matrix(new double[][] {
{1, 0, 0},
{0, 1, 0},
{0, 0, 0}
});
BufferedImage ball = null;
public CubeRotator() {
try {
ball = ImageIO.read(getClass().getResourceAsStream("ball.gif"));
} catch (IOException e) {
System.out.println(e);
}
}
public Matrix generateTransform(Axis axis, double theta) {
switch (axis) {
case X:
return new Matrix(new double[][] {
{1, 0, 0},
{0, Math.cos(theta), Math.sin(theta) * -1},
{0, Math.sin(theta), Math.cos(theta)}
});
case Y:
return new Matrix(new double[][] {
{Math.cos(theta), 0, Math.sin(theta)},
{0, 1, 0},
{Math.sin(theta) * -1, 0, Math.cos(theta)}
});
case Z:
return new Matrix(new double[][] {
{Math.cos(theta), Math.sin(theta) * - 1, 0},
{Math.sin(theta), Math.cos(theta), 0},
{0, 0, 1}
});
default:
return null;
}
}
@Override
public void update() {
Matrix testMatrixA = new Matrix(
new double[][] {
{0, 3, 5},
{5, 5, 2}
}
);
Matrix testMatrixB = new Matrix(
new double[][] {
{3, 4},
{3, -2},
{4, -2}
}
);
System.out.println(Matrix.getColumnAsArray(0, testMatrixB));
for (int i = 0; i < vertices.length; i++) {
verticesProjected[i] = vertices[i].getProduct(projectionMatrix);
}
}
@Override
public void draw(Graphics2D graphics2d) {
for (int i = 0; i < verticesProjected.length; i++) {
double[][] coords = verticesProjected[i].getMatrix();
graphics2d.drawImage(
ball,
null,
((int)coords[0][0] * scaleFactor) + offsetWidth,
((int)coords[0][1] * scaleFactor) + offsetHeight
);
}
}
}
@@ -1,0 +1,8 @@
package eyecandy;
import java.awt.Graphics2D;
public interface Drawable {
public void update();
public void draw(Graphics2D graphics2D);
}
@@ -1,0 +1,53 @@
package eyecandy;
import java.awt.Color;
public class Mandelbrot extends StackableBackground {
final int width = 320;
final int height = 200;
final int offsetX = width / 2;
final int offsetY = height / 2;
final int mandelCycles = 2000;
public Color getFractalValue(double c_r, double c_i) {
int i = 0;
double x = 0, y = 0;
/*
* Instead of creating an object for complex numbers I used two doubles.
* The reason is because there was some guy on a blog who explained it this way
* and I don't have the patience to make it work better
*/
while (x*x+y*y <= 4 && i < mandelCycles) {
double x_new = x*x - y*y + c_r;
y = 2*x*y + c_i;
x = x_new;
i++;
}
if (i < mandelCycles) {
return Color.white;
} else {
return Color.black;
}
}
@Override
public int getColour(int x, int y) {
/*int mandelValue = (int)iterate(
(double)(x - offsetX) / 40,
(double)(y - offsetY) / 40
);
mandelValue = Math.min(Math.abs(mandelValue / 5), 255);*/
return getFractalValue(
(double)(x - offsetX) / 80,
(double)(y - offsetY) / 80
).getRGB();
}
@Override
public int[] transformScreen() {
return new int[]{0, 0};
}
}
@@ -1,0 +1,113 @@
package eyecandy;
import java.awt.Color;
import java.lang.Math;
import absmaths.AbsMaths;
import absmaths.Matrix;
/*
* TODO:
* * remove rotationIteration [DONE]
* * remove plazmaIteration [DONE]
* * provide a way to switch modes with a cool transition
* * use LUTs to save compute time each time
* * export
*/
public class Modulo extends StackableBackground {
final int rotationIterationCycle = 768;
final int plazmaIterationCycle = 234;
final int plazmaSpeedFactor = 3;
final boolean procedural = true;
final Matrix transformYUVtoRGB = new Matrix(
new double[][] {
{1, 0, 1.13983},
{1, -0.39465, -0.58060},
{1, 2.03211, 0}
}
);
final int width = 640;
final int height = 400;
int timeOfLastTransition;
int[][] moduloTable = AbsMaths.newTimesTable(width, height);
public enum Modes {
HUE_MODE,
PAL_MODE,
GREY_MODE
}
public int getModuloTableEntry(int x) {
return (int) (
(x / (float)(
(
((Math.sin((float)iteration / (plazmaIterationCycle / plazmaSpeedFactor)) + 1) * (plazmaIterationCycle / 2)
) / 5
) + 0.25)) % 255
);
}
public int getColourThroughPAL(int x) {
x = getModuloTableEntry(x);
Matrix coloursYUV = new Matrix(new double[][]{
{0},
{255 - x},
{x},
});
double[] coloursRGB = AbsMaths.sanitizeToBounds(transformYUVtoRGB.getProduct(coloursYUV).getColumnAsArray(0), 0, 255);
Color color = new Color((int)coloursRGB[0], (int)coloursRGB[1], (int)coloursRGB[2]);
return color.getRGB();
}
public int getColourThroughHue(int x) {
float h = (float)getModuloTableEntry(x) / (255f / 6);
float w = (float)(1 - Math.abs((h % 2) - 1));
switch ((int)Math.floor(h)) {
case 0:
return new Color(1, w, 0).getRGB();
case 1:
return new Color(w, 1, 0).getRGB();
case 2:
return new Color(0, 1, w).getRGB();
case 3:
return new Color(0, w, 1).getRGB();
case 4:
return new Color(w, 0, 1).getRGB();
case 5:
return new Color(1, 0, w).getRGB();
default:
return 0;
}
}
public int getColourStraight(int x) {
x = getModuloTableEntry(x);
Color color = new Color(x, x, x);
return color.getRGB();
}
@Override
public int getColour(int x, int y) {
return getColourStraight(moduloTable[x][y]);
}
@Override
public int[] transformScreen() {
return new int[]{
(int) (Math.sin(((float)(iteration % rotationIterationCycle) / rotationIterationCycle) * 2 * Math.PI) * (width / 4) - (width / 4)),
(int) (Math.cos(((float)(iteration % rotationIterationCycle) / rotationIterationCycle) * 2 * Math.PI) * (height / 4) - (height / 4))
};
}
}
@@ -1,0 +1,137 @@
package eyecandy;
import java.awt.Color;
import java.awt.Graphics2D;
public class Sorter implements Drawable{
final int width = 320;
final int height = 200;
final int setLength = 93;
final int setRange = 100;
final int widthOffset = 20;
final int heightOffset = 150;
final int poleDistance = 3;
int[] set = new int[setLength];
int[] work = new int[setLength];
public enum Modes {
MERGE_MODE,
BUBBLE_MODE,
QUICK_MODE,
}
private Modes mode;
/*
private class BubbleRegisters {
int hold;
boolean changed;
}
private class MergeRegisters {
int x;
}
private class QuickRegisters {
int x;
}
*/
public Sorter() {
for (int i = 0; i < setLength; i++) {
set[i] = (int)Math.floor(Math.random() * setRange);
}
mode = Modes.BUBBLE_MODE;
}
public void setMode(Modes m) {
switch (m) {
case MERGE_MODE:
mode = Modes.MERGE_MODE;
break;
case BUBBLE_MODE:
mode = Modes.BUBBLE_MODE;
break;
case QUICK_MODE:
mode = Modes.QUICK_MODE;
break;
}
}
private int[] bubbleSort(int[] s) {
boolean changed = false;
do {
for (int i = 0; i < s.length - 1; i++) {
if (s[i] > s[i + 1]) {
int hold = s[i];
s[i] = s[i + 1];
s[i + 1] = hold;
}
}
} while (changed);
return s;
}
private int[] topDownMergeSort(int[] s, int n) {
int[] w = new int[s.length];
return s;
}
private void topDownSplitMerge() {
}
@Override
public void update() {
switch (mode) {
case MERGE_MODE:
set = topDownMergeSort(set);
break;
case BUBBLE_MODE:
set = bubbleSort(set);
break;
case QUICK_MODE:
break;
}
}
public void renderSet(int offset, Graphics2D graphics2d) {
for (int i = 0; i < setLength; i++) {
graphics2d.drawLine(
widthOffset + (i*poleDistance) + offset,
heightOffset,
widthOffset + (i*poleDistance) + offset,
heightOffset - set[i]
);
}
}
@Override
public void draw(Graphics2D graphics2d) {
switch (mode) {
case MERGE_MODE:
graphics2d.setColor(Color.cyan);
break;
case BUBBLE_MODE:
graphics2d.setColor(Color.magenta);
break;
case QUICK_MODE:
graphics2d.setColor(Color.green);
break;
}
renderSet(0, graphics2d);
switch (mode) {
case MERGE_MODE:
graphics2d.setColor(Color.blue);
break;
case BUBBLE_MODE:
graphics2d.setColor(Color.red);
break;
case QUICK_MODE:
graphics2d.setColor(Color.green);
break;
}
graphics2d.setColor(Color.black);
renderSet(2, graphics2d);
}
}
@@ -1,0 +1,51 @@
package eyecandy;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
public class StackableBackground implements Drawable {
final int width = 640;
final int height = 400;
int iteration = 0;
boolean procedural = false;
BufferedImage canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
public int getColour(int x, int y) {
return 255;
}
@Override
public void update() {
iteration++;
if (iteration < 0) {
iteration = Math.abs(iteration);
}
for (int x=0; x<width; x++) {
for (int y=0; y<height; y++) {
canvas.setRGB(x, y, getColour(x, y));
}
}
}
public int[] transformScreen() {
return new int[] {0, 0};
}
@Override
public void draw(Graphics2D graphics2D) {
int[] currentTransform = transformScreen();
graphics2D.drawImage(
canvas,
null,
currentTransform[0],
currentTransform[1]
);
}
}
Binary files /dev/null and a/src/eyecandy/ball.gif differ
Binary files /dev/null and a/src/eyecandy/fontsheet.gif differ
@@ -1,0 +1,83 @@
package main;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
import eyecandy.Modulo;
import eyecandy.Sorter;
import eyecandy.CubeRotator;
import eyecandy.Mandelbrot;
public class DemoPanel extends JPanel implements Runnable {
private static final long serialVersionUID = -3550958944572506053L;
final int scale = 3;
final int screenWidth = 320;
final int screenHeight = 200;
final int FPS = 60;
final double drawInterval = 1000000000/FPS;
double nextDrawTime;
double remainingTime;
Thread demoThread;
CubeRotator modulo = new CubeRotator();
KeyHandler keyHandler = new KeyHandler();
public DemoPanel() {
this.setPreferredSize(new Dimension(screenWidth, screenHeight));
this.setBackground(Color.black);
this.setDoubleBuffered(true);
}
public void initDemo() {
demoThread = new Thread(this);
demoThread.start();
}
@Override
public void run() {
while (demoThread != null) {
update();
repaint();
try {
nextDrawTime = System.nanoTime() + drawInterval;
remainingTime = nextDrawTime - System.nanoTime();
remainingTime = remainingTime / 1000000;
if (remainingTime < 0) {
remainingTime = 0;
}
Thread.sleep((long) remainingTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void update() {
modulo.update();
}
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g2 = (Graphics2D)graphics;
modulo.draw(g2);
g2.dispose();
}
}
@@ -1,0 +1,35 @@
package main;
import java.awt.event.KeyEvent;
/*
* This class only exists for development's sake, do not intend to use it in the final product.
*/
import java.awt.event.KeyListener;
public class KeyHandler implements KeyListener {
public int lastTyped = -1;
@Override
public void keyTyped(KeyEvent e) {
lastTyped = e.getKeyCode();
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
public void clearTypeBuffer() {
lastTyped = -1;
}
}
@@ -1,0 +1,27 @@
package main;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
DemoPanel demoPanel = new DemoPanel();
window.add(demoPanel);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
demoPanel.initDemo();
}
}