package mandelbrot;
import easyplot.color.Colorizer;
import easyplot.color.LinearGradientColorizer;
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.nio.FloatBuffer;
import vecpy.VecPy;
public class Main {
public static final int max = 100;
public static final int w = 801;
public static final int h = 601;
public static final int N = w * h;
public static final float w_m1 = w - 1, h_m1 = h - 1;
public static float dx = 0f, dy = 0, sx = 4, sy = 3;
private static double time;
private static Colorizer color;
public static void main(String[] args) throws Exception {
Color[] colors = new Color[]{
Color.black,
new Color(128, 0, 255),
Color.black,
new Color(255, 128, 0),
Color.black,
new Color(0, 255, 128),
Color.black,
new Color(0, 128, 255),
Color.black,
new Color(128, 255, 0),
Color.black,
new Color(255, 0, 128),
Color.black
};
color = new LinearGradientColorizer(LinearGradientColorizer.getUniformStops(colors.length), colors);
System.load("/home/undefined/NetBeansProjects/VecPy_Mandelbrot/VecPy_mandelbrot.so");
FloatBuffer row = VecPy.getFloatBuffer(N);
FloatBuffer col = VecPy.getFloatBuffer(N);
FloatBuffer count = VecPy.getFloatBuffer(N);
for (int r = 0; r < h; r++) {
for (int c = 0; c < w; c++) {
row.put(r);
col.put(c);
}
}
GraphicsDevice screen = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
DisplayMode newDisplayMode = null;
DisplayMode oldDisplayMode = screen.getDisplayMode();
for (DisplayMode dm : screen.getDisplayModes()) {
if (dm.getWidth() == w && dm.getHeight() == h && dm.getRefreshRate() == 60) {
newDisplayMode = dm;
break;
}
}
Window window = new Window(newDisplayMode != null);
window.setVisible(true);
try {
if (newDisplayMode != null) {
screen.setFullScreenWindow(window);
screen.setDisplayMode(newDisplayMode);
}
double fps = 0;
long lastUpdate = System.currentTimeMillis() - 16;
while (true) {
row.rewind();
col.rewind();
count.rewind();
float left = dx - sx / 2f;
float right = left + sx;
float bottom = dy - sy / 2f;
float top = bottom + sy;
long start = System.nanoTime();
boolean result = VecPy.mandelbrot(row, col, count, max, w_m1, h_m1, left, right, top, bottom);
long end = System.nanoTime();
if (!result) {
throw new Exception("kernel failed");
}
for (int r = 0; r < h; r++) {
for (int c = 0; c < w; c++) {
window.display.buffer.setRGB(c, r, getRGB(count.get() / (double) max));
}
}
long thisUpdate = System.currentTimeMillis();
fps = fps * 0.9 + (1000.0 / (thisUpdate - lastUpdate)) * 0.1;
double delta = (thisUpdate - lastUpdate) / 1000.0;
time += delta;
cr += Math.sin(time * 3) * .0003;
ci += Math.cos(time * 1) * .0001;
lastUpdate = thisUpdate;
Graphics g = window.display.buffer.getGraphics();
g.setColor(Color.green);
String timer = String.format("%.1fms", (end - start) / 1e6d);
g.drawString(timer, 5, 15);
window.display.repaint();
// Thread.sleep(10);
}
} finally {
if (newDisplayMode != null) {
screen.setDisplayMode(oldDisplayMode);
screen.setFullScreenWindow(null);
}
}
}
private static final double LOG2 = Math.log(2);
private static boolean mandelbrot(FloatBuffer row_, FloatBuffer col_, FloatBuffer count_, float max, float w_m1, float h_m1, float left, float right, float top, float bottom) {
for (int index = 0; index < N; index++) {
float row = row_.get();
float col = col_.get();
float x0 = left + col * (right - left) / w_m1;
float y0 = bottom + (h_m1 - row) * (top - bottom) / h_m1;
float x = 0, y = 0;
float count = 0;
float xx = x * x;
float yy = y * y;
//Standard escape time
while (count < max && xx + yy < 16) {
float temp = xx - yy + x0;
y = 2 * x * y + y0;
x = temp;
xx = x * x;
yy = y * y;
++count;
}
//Smooth shading
if (count < max) {
count += 1 - Math.log(Math.log(xx + yy) / LOG2 / 2.0) / LOG2;
}
count_.put(count);
}
count_.rewind();
return true;
}
private static int getRGB(double d) {
Color c = color.getColor((time * .02 + d) % 1);
return c.getRGB();
}
}
package mandelbrot;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame {
public Display display;
public Window(boolean fullscreen) throws HeadlessException {
super("VecPy Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setUndecorated(fullscreen);
setResizable(false);
display = new Display();
add(display);
pack();
setLocationRelativeTo(null);
}
public class Display extends JPanel implements MouseMotionListener, MouseWheelListener {
public BufferedImage buffer;
public int x, y;
public Display() {
buffer = new BufferedImage(Main.w, Main.h, BufferedImage.TYPE_INT_RGB);
setPreferredSize(new Dimension(Main.w, Main.h));
addMouseMotionListener(this);
addMouseWheelListener(this);
}
@Override
public void paint(Graphics g) {
g.drawImage(buffer, 0, 0, null);
}
@Override
public void mouseDragged(MouseEvent e) {
Main.dx += -(e.getX() - x) / (float) Main.w * Main.sx;
Main.dy += (e.getY() - y) / (float) Main.h * Main.sy;
x = e.getX();
y = e.getY();
}
@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
int i = e.getWheelRotation();
float ratio = 1.2f;
if (i < 0) {
ratio = 1 / ratio;
i *= -1;
}
while (i-- > 0) {
Main.sx *= ratio;
Main.sy *= ratio;
}
}
}
}