You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

335 lines
12 KiB
Java

package deepZoom;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import deepZoom.calculator.Calculator;
import deepZoom.calculator.ParallelCalculator;
import deepZoom.colorings.Coloring;
import deepZoom.colorings.SmoothIterationsColoringBad;
import deepZoom.fractals.Fractal;
import deepZoom.fractals.Mandel;
import deepZoom.fractals.MandelPrecision;
import deepZoom.parameters.ZoomAnimation;
import deepZoom.renderer.Layer;
import deepZoom.renderer.Scene;
import deepZoom.schedulers.AngularScheduler;
import deepZoom.schedulers.CRTScheduler;
import deepZoom.schedulers.ClockScheduler;
import deepZoom.schedulers.DitherScheduler;
import deepZoom.schedulers.FlowerScheduler;
import deepZoom.schedulers.ModScheduler;
import deepZoom.schedulers.PythagorasScheduler;
import deepZoom.schedulers.RadialScheduler;
import deepZoom.schedulers.RandomScheduler;
import deepZoom.schedulers.Scheduler;
import deepZoom.schedulers.SimpleScheduler;
import deepZoom.schedulers.SpiralScheduler;
import deepZoom.schedulers.SplitScheduler;
import deepZoom.schedulers.SquareSpiralScheduler;
import deepZoom.schedulers.XorScheduler;
import deepZoom.viewports.Viewport;
import digisoft.custom.NumberFunctions;
import digisoft.custom.awt.Color3f;
import digisoft.custom.swing.ImageFunctions;
import digisoft.custom.swing.RefreshListener;
import digisoft.custom.swing.RefreshThread;
import digisoft.custom.swing.gradient.Gradient;
import digisoft.custom.swing.gradient.OpaqueGradient;
import digisoft.custom.swing.window.PixelWindow;
import digisoft.custom.util.geom.DoubleDouble;
import java.io.File;
/**
* @author Zom-B
* @since 1.0
* @see date 2006/10/20
*/
public class MandelAnimator implements RefreshListener, Calculator, MouseListener {
private static final String SAVEPATH = "C:/Animation golden/";
private static final int WIDTH = (int) (1024);
private static final int HEIGHT = (int) (576);
private static int FRAME_START = 1;
private static final int FRAME_END = 3600;
private static final int FRAME_STEP = 1;
private static final boolean DO_ANTIALIAS = true;
//Traditional Wikipedia
private DoubleDouble centerX = new DoubleDouble(-0.7436438870371587, -3.628952515063387E-17);
private DoubleDouble centerY = new DoubleDouble(0.13182590420531198, -1.2892807754956678E-17);
//Line and cross
//private DoubleDouble centerX = new DoubleDouble(-0.743646040973709, -4.790419761500457E-18);
//private DoubleDouble centerY = new DoubleDouble(0.13182426946026354, 1.9785505600065397E-18);
private static final double MIN_ZOOM = 1;
private static final double MAX_ZOOM = 1e30;
private static final int NUM_FRAMES = 3600;
public static void main(String[] args) {
new MandelAnimator();
}
private static final int NUM_CPUS = Runtime.getRuntime().availableProcessors();
private PixelWindow aaWindow = new PixelWindow(10, 10, MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
private PixelWindow iterWindow = new PixelWindow(10, 10, MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
private PixelWindow fractalWindow = new PixelWindow(10, 10, MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
private Viewport viewport = new Viewport();
private Layer layer = new Layer();
private ZoomAnimation animation = new ZoomAnimation();
private Fractal fractal = new Mandel();
private Coloring coloring = new SmoothIterationsColoringBad(makeGradient());
private Scheduler[] schedulers = {new SpiralScheduler(10)};
private int scheduler;
private Scene scene = new Scene();
private int frameNr;
private boolean antialiasStep = false;
private long runTime;
private long frameTime;
public MandelAnimator() {
File dirFile = new File(SAVEPATH);
dirFile.mkdir();
int newSave = 0;
for (int i = MandelAnimator.FRAME_START; i <= MandelAnimator.FRAME_END; i++) {
File test = new File(MandelAnimator.SAVEPATH
+ NumberFunctions.toStringFixedLength(i, 4) + ".png");
if (!test.isFile()) {
newSave = i;
break;
}
}
MandelAnimator.FRAME_START = newSave;
fractalWindow.addMouseListener(this);
iterWindow.setTitle("Iter");
aaWindow.setTitle("AA");
animation.setWidth(MandelAnimator.WIDTH);
animation.setNumFrames(MandelAnimator.NUM_FRAMES);
animation.setCenterX(centerX);
animation.setCenterY(centerY);
animation.setMagnStart(MandelAnimator.MIN_ZOOM);
animation.setMagnEnd(MandelAnimator.MAX_ZOOM);
animation.setBailout(128);
animation.init();
viewport.setSize(MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
viewport.setParameters(animation);
fractal.setParameters(animation);
coloring.setParameters(animation);
for (Scheduler s : schedulers) {
s.setViewport(viewport);
}
scene.setViewport(viewport);
scene.setColorPixels(fractalWindow.pixels);
scene.setIterMap(iterWindow.pixels);
scene.setEdgeMap(aaWindow.pixels);
scene.setNumCPUs(MandelAnimator.NUM_CPUS);
{
layer.setFractal(fractal);
layer.setColoring(coloring);
scene.addLayer(layer);
}
frameNr = MandelAnimator.FRAME_START;
runTime = frameTime = System.currentTimeMillis();
ParallelCalculator.createCalculators(this, MandelAnimator.NUM_CPUS);
new RefreshThread(this, 30).start();
}
public static Gradient makeGradient() {
final Color3f[] c = {
new Color3f(14, 11, 82),
new Color3f(14, 60, 165),
new Color3f(78, 154, 220),
new Color3f(176, 229, 255),
new Color3f(249, 253, 239),
new Color3f(249, 229, 96),
new Color3f(249, 181, 15),
new Color3f(217, 108, 3),
new Color3f(134, 32, 13),
new Color3f(57, 4, 35),
new Color3f(14, 11, 82)};
final float[] f = new float[c.length];
for (int i = 0; i < c.length; i++) {
f[i] = i / (float) (c.length - 1);
f[i] = (float) StrictMath.sqrt(f[i]);
}
return new OpaqueGradient(f, c);
}
/*
public static Gradient makeGradient() {
final Color3f[] c = {new Color3f(0, 0, 0f), //
new Color3f(1, 0, 0f), //
new Color3f(1, 1, 1f), // Red
new Color3f(1, 0, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(1, 0.4f, 0f), //
new Color3f(1, 1, 1f), // Orange
new Color3f(1, 0.4f, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(1, 1, 0f), //
new Color3f(1, 1, 1f), // Yellow
new Color3f(1, 1, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(0, 1, 0f), //
new Color3f(1, 1, 1f), // Green
new Color3f(0, 1, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(0, 1, 1f), //
new Color3f(1, 1, 1f), // Cyan
new Color3f(0, 1, 1f), //
new Color3f(0, 0, 0f), //
new Color3f(0, 0, 1f), //
new Color3f(1, 1, 1f), // Blue
new Color3f(0, 0, 1f), //
new Color3f(0, 0, 0f)};
final float[] f = new float[c.length];
for (int i = 0; i < c.length; i++) {
f[i] = i / (float) (c.length - 1);
f[i] = (float) StrictMath.sqrt(f[i]);
}
return new OpaqueGradient(f, c);
} */
private void saveFrame() {
try {
ImageFunctions.savePNG(MandelAnimator.SAVEPATH + NumberFunctions.toStringFixedLength(frameNr, 4) + ".png", fractalWindow.pixels,
MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
} catch (IOException e) {
e.printStackTrace();
}
}
private void destroyImage() {
System.gc();
fractalWindow.clear(0);
iterWindow.clear(0);
aaWindow.clear(0);
}
private void nextFrame() {
frameNr += MandelAnimator.FRAME_STEP;
if (frameNr > MandelAnimator.FRAME_END) {
// System.exit(0);
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void prepareCalculation() {
scheduler = NumberFunctions.RND.nextInt(schedulers.length);
scene.setScheduler(schedulers[scheduler]);
if (!antialiasStep) {
fractalWindow.setTitle(Integer.toString(frameNr) + " First pass");
animation.setFrame(frameNr);
System.out.println("Rough: " + frameNr + " magn=" + animation.getMagn() + " maxiter=" + animation.getMaxiter());
destroyImage();
scene.initFrame();
} else {
fractalWindow.setTitle(Integer.toString(frameNr) + " Antialiasing");
animation.setFrame(frameNr);
animation.setMaxiter(animation.getMaxiter() << 2);
System.out.println("AA: " + frameNr + " magn=" + animation.getMagn() + " maxiter=" + animation.getMaxiter());
scene.calcAntialiasMask();
}
schedulers[scheduler].init();
}
@Override
public void calculate(int cpu) {
if (!antialiasStep) {
scene.render(cpu);
} else {
scene.renderAntialias(cpu);
}
}
@Override
public void calculationCompleted() {
if (!antialiasStep && MandelAnimator.DO_ANTIALIAS) {
antialiasStep = true;
} else {
antialiasStep = false;
fractalWindow.repaintNow();
iterWindow.repaintNow();
saveFrame();
long time = System.currentTimeMillis();
System.out.println("Time elapsed: " + (time - runTime) / 1e3 + " / " + (time - frameTime) / 1e3);
if (time - frameTime < 2000) {
try {
Thread.sleep(2000 - time + frameTime);
} catch (InterruptedException e) {
}
}
frameTime = System.currentTimeMillis();
nextFrame();
}
}
@Override
public void refreshing() {
fractalWindow.repaintNow();
iterWindow.repaintNow();
aaWindow.repaintNow();
if (antialiasStep) {
aaWindow.setTitle("AA " + (int) (schedulers[scheduler].getProgress() * 1000) / 10f + "%");
} else {
iterWindow.setTitle("Iter " + (int) (schedulers[scheduler].getProgress() * 1000) / 10f + "%");
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
centerX = viewport.getPX(e.getX(), e.getY());
centerY = viewport.getPY(e.getX(), e.getY());
System.out.println("/tprivate DoubleDouble/t/t/tcenterX/t/t/t= new DoubleDouble(" + centerX.hi + ", " + centerX.lo + ");");
System.out.println("/tprivate DoubleDouble/t/t/tcenterY/t/t/t= new DoubleDouble(" + centerY.hi + ", " + centerY.lo + ");");
} else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
}