Created
November 15, 2017 03:21
-
-
Save manse/ca96ffeb77e8a47d798a2d9632e019be to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. | |
// Jad home page: http://www.kpdus.com/jad.html | |
// Decompiler options: packimports(3) | |
// Source File Name: LatticedLiquid2.java | |
import java.applet.Applet; | |
import java.awt.*; | |
import java.awt.event.*; | |
import java.awt.image.MemoryImageSource; | |
import java.util.Arrays; | |
public class LatticedLiquid2 extends Applet | |
implements Runnable, MouseListener, MouseMotionListener, KeyListener | |
{ | |
public LatticedLiquid2() | |
{ | |
airDensity = 0.001D; | |
minMass = 9.9999999999999995E-07D; | |
equalizerBias = 9.9999999999999995E-07D; | |
gravityX = 0.0D; | |
gravityY = 0.5D; | |
tension = 0.80000000000000004D; | |
} | |
public synchronized void init() | |
{ | |
try | |
{ | |
scale = Integer.parseInt(getParameter("scale")); | |
} | |
catch(RuntimeException runtimeexception) { } | |
xbits = Math.max(4, (int)Math.round(Math.log(getWidth()) / Math.log(2D)) - scale); | |
ybits = Math.max(4, (int)Math.round(Math.log(getHeight()) / Math.log(2D)) - scale); | |
xmax = (1 << xbits) - 1; | |
ymax = (1 << ybits) - 1; | |
shift = xbits; | |
size = 1 << xbits + ybits; | |
air = new double[size + 1]; | |
liq = new double[size + 1]; | |
room = new double[size + 1]; | |
velocityX = new double[size + 1]; | |
velocityY = new double[size + 1]; | |
minVelocityX = new double[size + 1]; | |
minVelocityY = new double[size + 1]; | |
maxVelocityX = new double[size + 1]; | |
maxVelocityY = new double[size + 1]; | |
momentumX = new double[size + 1]; | |
momentumY = new double[size + 1]; | |
airBuffer = new double[size + 1]; | |
liqBuffer = new double[size + 1]; | |
airFluxX = new double[size + 1]; | |
airFluxY = new double[size + 1]; | |
liqFluxX = new double[size + 1]; | |
liqFluxY = new double[size + 1]; | |
pressure = new Grid(xbits, ybits); | |
equalizer = new Grid(xbits, ybits); | |
pixels = new int[size + 1]; | |
imageSource = new MemoryImageSource(1 << xbits, 1 << ybits, pixels, 0, 1 << xbits); | |
imageSource.setAnimated(true); | |
image = getToolkit().createImage(imageSource); | |
addMouseListener(this); | |
addMouseMotionListener(this); | |
addKeyListener(this); | |
} | |
public synchronized void start() | |
{ | |
reset(1); | |
thread = new Thread(this); | |
thread.setDaemon(true); | |
thread.start(); | |
} | |
private synchronized void reset(int type) | |
{ | |
Arrays.fill(air, 0.0D); | |
Arrays.fill(liq, 0.0D); | |
Arrays.fill(momentumX, 0.0D); | |
Arrays.fill(momentumY, 0.0D); | |
Arrays.fill(velocityX, 0.0D); | |
Arrays.fill(velocityY, 0.0D); | |
Arrays.fill(minVelocityX, -xmax); | |
Arrays.fill(maxVelocityX, xmax); | |
Arrays.fill(minVelocityY, -ymax); | |
Arrays.fill(maxVelocityY, ymax); | |
switch(type) | |
{ | |
case 1: // '\001' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
if(x != 0 && x != xmax && y != 0 && y != ymax) | |
if(x < xmax / 2) | |
liq[i] = 1.0D; | |
else | |
air[i] = 1.0D; | |
minVelocityX[i] = Math.min(0, 1 - x); | |
maxVelocityX[i] = Math.max(0, xmax - 1 - x); | |
minVelocityY[i] = Math.min(0, 1 - y); | |
maxVelocityY[i] = Math.max(0, ymax - 1 - y); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 2: // '\002' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
if(y != 0 && y != ymax) | |
if(y > ymax / 2) | |
liq[i] = 1.0D; | |
else | |
air[i] = 1.0D; | |
minVelocityX[i] = -xmax; | |
maxVelocityX[i] = xmax; | |
minVelocityY[i] = Math.min(0, 1 - y); | |
maxVelocityY[i] = Math.max(0, ymax - 1 - y); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 3: // '\003' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
if(y != 0 && y != ymax) | |
if(y < ymax / 2) | |
liq[i] = 1.0D; | |
else | |
air[i] = 1.0D; | |
minVelocityX[i] = -xmax; | |
maxVelocityX[i] = xmax; | |
minVelocityY[i] = Math.min(0, 1 - y); | |
maxVelocityY[i] = Math.max(0, ymax - 1 - y); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 4: // '\004' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
if(x != 0 && x != xmax && y != 0 && y != ymax && (x <= xmax / 4 || x >= (xmax * 3) / 4 || y <= ymax / 4 || y >= (ymax * 3) / 4)) | |
if(y > ymax / 2) | |
liq[i] = 1.0D; | |
else | |
air[i] = 1.0D; | |
minVelocityX[i] = Math.min(0, 1 - x); | |
maxVelocityX[i] = Math.max(0, xmax - 1 - x); | |
minVelocityY[i] = Math.min(0, 1 - y); | |
maxVelocityY[i] = Math.max(0, ymax - 1 - y); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 5: // '\005' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
if(x != xmax / 3 && y != ymax / 3) | |
if(y > ymax / 2) | |
liq[i] = 1.0D; | |
else | |
air[i] = 1.0D; | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 6: // '\006' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double w = Math.max(0.0D, Math.min((double)(Math.min(xmax, ymax) / 2 - 2) - Math.hypot(x - xmax / 2, y - ymax / 2), 1.0D)); | |
if(y > ymax / 2) | |
liq[i] = w; | |
else | |
air[i] = w; | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
default: | |
{ | |
return; | |
} | |
} | |
for(int i = 0; i < size; i++) | |
room[i] = air[i] + liq[i]; | |
} | |
public void run() | |
{ | |
while(!Thread.interrupted()) | |
{ | |
updatePhase(); | |
updateImage(); | |
try | |
{ | |
Thread.sleep(20L); | |
continue; | |
} | |
catch(InterruptedException e) { } | |
break; | |
} | |
} | |
private synchronized void updatePhase() | |
{ | |
applyForce(); | |
applyAdvection(); | |
applyEqualization(); | |
} | |
private void applyForce() | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x - 1 & xmax | y << shift; | |
double r = Math.min(room[i], room[j]); | |
double a = air[i] + air[j]; | |
double b = liq[i] + liq[j]; | |
double m = airDensity * a + b; | |
double p = 2D * momentumX[i] + m * gravityX; | |
m = Math.max(m, minMass); | |
velocityX[i] = (r * p) / m; | |
pressure.linkX[i] = r / m; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x | (y - 1 & ymax) << shift; | |
double r = Math.min(room[i], room[j]); | |
double a = air[i] + air[j]; | |
double b = liq[i] + liq[j]; | |
double m = airDensity * a + b; | |
double p = 2D * momentumY[i] + m * gravityY; | |
m = Math.max(m, minMass); | |
velocityY[i] = (r * p) / m; | |
pressure.linkY[i] = r / m; | |
x++; | |
i++; | |
} | |
} | |
if(lastMousePoint != null) | |
{ | |
cursorVelocityX += (2D * (((double)lastMousePoint.x - cursorX) / 5D - cursorVelocityX)) / 5D; | |
cursorVelocityY += (2D * (((double)lastMousePoint.y - cursorY) / 5D - cursorVelocityY)) / 5D; | |
double scaledCursorX = (cursorX / (double)getWidth()) * (double)xmax; | |
double scaledCursorY = (cursorY / (double)getHeight()) * (double)ymax; | |
double scaledVelocityX = (cursorVelocityX / (double)getWidth()) * (double)xmax; | |
double scaledVelocityY = (cursorVelocityY / (double)getHeight()) * (double)ymax; | |
applyMouse(scaledCursorX, scaledCursorY, scaledVelocityX, scaledVelocityY, 10D); | |
cursorX += cursorVelocityX; | |
cursorY += cursorVelocityY; | |
} | |
scaledCursorX = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
pressure.source[scaledCursorX] = ((velocityX[scaledCursorX] - velocityX[x + 1 & xmax | y << shift]) + velocityY[scaledCursorX]) - velocityY[x | (y + 1 & ymax) << shift]; | |
x++; | |
scaledCursorX++; | |
} | |
} | |
pressure.solve(10); | |
scaledCursorX = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x - 1 & xmax | y << shift; | |
double p = pressure.value[j] - pressure.value[scaledCursorX]; | |
velocityX[scaledCursorX] += pressure.linkX[scaledCursorX] * p; | |
x++; | |
scaledCursorX++; | |
} | |
} | |
scaledCursorX = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x | (y - 1 & ymax) << shift; | |
double p = pressure.value[j] - pressure.value[scaledCursorX]; | |
velocityY[scaledCursorX] += pressure.linkY[scaledCursorX] * p; | |
x++; | |
scaledCursorX++; | |
} | |
} | |
} | |
private void applyAdvection() | |
{ | |
Arrays.fill(airBuffer, 0.0D); | |
Arrays.fill(liqBuffer, 0.0D); | |
Arrays.fill(momentumX, 0.0D); | |
Arrays.fill(momentumY, 0.0D); | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double vx0 = velocityX[i]; | |
double vx1 = velocityX[x + 1 & xmax | y << shift]; | |
double vy0 = velocityY[i]; | |
double vy1 = velocityY[x | (y + 1 & ymax) << shift]; | |
double gx = tension * (liq[x - 1 & xmax | y << shift] - liq[x + 1 & xmax | y << shift]); | |
double gy = tension * (liq[x | (y - 1 & ymax) << shift] - liq[x | (y + 1 & ymax) << shift]); | |
double vx = Math.max(minVelocityX[i], Math.min(0.5D * (vx0 + vx1 + gx), maxVelocityX[i])); | |
double vy = Math.max(minVelocityY[i], Math.min(0.5D * (vy0 + vy1 + gy), maxVelocityY[i])); | |
double dx = (double)(x + xmax + 1) + vx; | |
double dy = (double)(y + ymax + 1) + vy; | |
int ix = (int)dx; | |
int iy = (int)dy; | |
dx -= ix; | |
dy -= iy; | |
double w00 = (1.0D - dx) * (1.0D - dy); | |
double w01 = (1.0D - dx) * dy; | |
double w10 = dx * (1.0D - dy); | |
double w11 = dx * dy; | |
int x0 = ix & xmax; | |
int y0 = (iy & ymax) << shift; | |
int x1 = ix + 1 & xmax; | |
int y1 = (iy + 1 & ymax) << shift; | |
int x2 = ix + 2 & xmax; | |
int y2 = (iy + 2 & ymax) << shift; | |
double a = air[i]; | |
double m = 0.5D * airDensity * a; | |
airBuffer[x0 | y0] += a * w00; | |
airBuffer[x0 | y1] += a * w01; | |
airBuffer[x1 | y0] += a * w10; | |
airBuffer[x1 | y1] += a * w11; | |
momentumX[x0 | y0] += m * vx0 * w00; | |
momentumX[x1 | y0] += m * vx0 * w10 + m * vx1 * w00; | |
momentumX[x2 | y0] += m * vx1 * w10; | |
momentumX[x0 | y1] += m * vx0 * w01; | |
momentumX[x1 | y1] += m * vx0 * w11 + m * vx1 * w01; | |
momentumX[x2 | y1] += m * vx1 * w11; | |
momentumY[x0 | y0] += m * vy0 * w00; | |
momentumY[x0 | y1] += m * vy0 * w01 + m * vy1 * w00; | |
momentumY[x0 | y2] += m * vy1 * w01; | |
momentumY[x1 | y0] += m * vy0 * w10; | |
momentumY[x1 | y1] += m * vy0 * w11 + m * vy1 * w10; | |
momentumY[x1 | y2] += m * vy1 * w11; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double vx0 = velocityX[i]; | |
double vx1 = velocityX[x + 1 & xmax | y << shift]; | |
double vy0 = velocityY[i]; | |
double vy1 = velocityY[x | (y + 1 & ymax) << shift]; | |
double gx = tension * (air[x - 1 & xmax | y << shift] - air[x + 1 & xmax | y << shift]); | |
double gy = tension * (air[x | (y - 1 & ymax) << shift] - air[x | (y + 1 & ymax) << shift]); | |
double vx = Math.max(minVelocityX[i], Math.min(0.5D * (vx0 + vx1 + gx), maxVelocityX[i])); | |
double vy = Math.max(minVelocityY[i], Math.min(0.5D * (vy0 + vy1 + gy), maxVelocityY[i])); | |
double dx = (double)(x + xmax + 1) + vx; | |
double dy = (double)(y + ymax + 1) + vy; | |
int ix = (int)dx; | |
int iy = (int)dy; | |
dx -= ix; | |
dy -= iy; | |
double w00 = (1.0D - dx) * (1.0D - dy); | |
double w01 = (1.0D - dx) * dy; | |
double w10 = dx * (1.0D - dy); | |
double w11 = dx * dy; | |
int x0 = ix & xmax; | |
int y0 = (iy & ymax) << shift; | |
int x1 = ix + 1 & xmax; | |
int y1 = (iy + 1 & ymax) << shift; | |
int x2 = ix + 2 & xmax; | |
int y2 = (iy + 2 & ymax) << shift; | |
double b = liq[i]; | |
double m = 0.5D * b; | |
liqBuffer[x0 | y0] += b * w00; | |
liqBuffer[x0 | y1] += b * w01; | |
liqBuffer[x1 | y0] += b * w10; | |
liqBuffer[x1 | y1] += b * w11; | |
momentumX[x0 | y0] += m * vx0 * w00; | |
momentumX[x1 | y0] += m * vx0 * w10 + m * vx1 * w00; | |
momentumX[x2 | y0] += m * vx1 * w10; | |
momentumX[x0 | y1] += m * vx0 * w01; | |
momentumX[x1 | y1] += m * vx0 * w11 + m * vx1 * w01; | |
momentumX[x2 | y1] += m * vx1 * w11; | |
momentumY[x0 | y0] += m * vy0 * w00; | |
momentumY[x0 | y1] += m * vy0 * w01 + m * vy1 * w00; | |
momentumY[x0 | y2] += m * vy1 * w01; | |
momentumY[x1 | y0] += m * vy0 * w10; | |
momentumY[x1 | y1] += m * vy0 * w11 + m * vy1 * w10; | |
momentumY[x1 | y2] += m * vy1 * w11; | |
x++; | |
i++; | |
} | |
} | |
System.arraycopy(airBuffer, 0, air, 0, size); | |
System.arraycopy(liqBuffer, 0, liq, 0, size); | |
} | |
private void applyEqualization() | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x - 1 & xmax | y << shift; | |
double r = Math.min(room[i], room[j]); | |
double a = air[i] + air[j]; | |
double b = liq[i] + liq[j]; | |
double m = Math.max(airDensity * a + b, minMass); | |
equalizer.linkX[i] = (r * (a + b)) / m + 2D * equalizerBias; | |
airFluxX[i] = (r * a) / m + equalizerBias; | |
liqFluxX[i] = (r * b) / m + equalizerBias; | |
velocityX[i] = (2D * r * momentumX[i]) / m; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x | (y - 1 & ymax) << shift; | |
double r = Math.min(room[i], room[j]); | |
double a = air[i] + air[j]; | |
double b = liq[i] + liq[j]; | |
double m = Math.max(airDensity * a + b, minMass); | |
equalizer.linkY[i] = (r * (a + b)) / m + 2D * equalizerBias; | |
airFluxY[i] = (r * a) / m + equalizerBias; | |
liqFluxY[i] = (r * b) / m + equalizerBias; | |
velocityY[i] = (2D * r * momentumY[i]) / m; | |
x++; | |
i++; | |
} | |
} | |
for(i = 0; i < size; i++) | |
equalizer.source[i] = (air[i] + liq[i]) - room[i]; | |
equalizer.solve(5); | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x - 1 & xmax | y << shift; | |
double p = equalizer.value[j] - equalizer.value[i]; | |
airFluxX[i] *= p; | |
liqFluxX[i] *= p; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int j = x | (y - 1 & ymax) << shift; | |
double p = equalizer.value[j] - equalizer.value[i]; | |
airFluxY[i] *= p; | |
liqFluxY[i] *= p; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int ix = x + 1 & xmax | y << shift; | |
int iy = x | (y + 1 & ymax) << shift; | |
airBuffer[i] = Math.min(1.0D, air[i] / ((((9.9999999999999995E-07D + Math.max(0.0D, airFluxX[ix])) - Math.min(0.0D, airFluxX[i])) + Math.max(0.0D, airFluxY[iy])) - Math.min(0.0D, airFluxY[i]))); | |
liqBuffer[i] = Math.min(1.0D, liq[i] / ((((9.9999999999999995E-07D + Math.max(0.0D, liqFluxX[ix])) - Math.min(0.0D, liqFluxX[i])) + Math.max(0.0D, liqFluxY[iy])) - Math.min(0.0D, liqFluxY[i]))); | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int ix = x - 1 & xmax | y << shift; | |
int iy = x | (y - 1 & ymax) << shift; | |
double ax = airFluxX[i]; | |
double ay = airFluxY[i]; | |
double bx = liqFluxX[i]; | |
double by = liqFluxY[i]; | |
airFluxX[i] = ax * airBuffer[ax <= 0.0D ? i : ix]; | |
airFluxY[i] = ay * airBuffer[ay <= 0.0D ? i : iy]; | |
liqFluxX[i] = bx * liqBuffer[bx <= 0.0D ? i : ix]; | |
liqFluxY[i] = by * liqBuffer[by <= 0.0D ? i : iy]; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double a = airFluxX[i]; | |
double b = liqFluxX[i]; | |
double m = 0.5D * (airDensity * a + b); | |
int ix0 = x - 1 & xmax | y << shift; | |
int ix1 = x + 1 & xmax | y << shift; | |
int iy1 = x | (y + 1 & ymax) << shift; | |
int ixy = x - 1 & xmax | (y + 1 & ymax) << shift; | |
double px0 = m * velocityX[m <= 0.0D ? i : ix0]; | |
double px1 = m * velocityX[m <= 0.0D ? ix1 : i]; | |
double py0 = m * velocityY[m <= 0.0D ? i : ix0]; | |
double py1 = m * velocityY[m <= 0.0D ? iy1 : ixy]; | |
momentumX[ix0] -= px0; | |
momentumX[i] += px0 - px1; | |
momentumX[ix1] += px1; | |
momentumY[ix0] -= py0; | |
momentumY[i] += py0; | |
momentumY[ixy] -= py1; | |
momentumY[iy1] += py1; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double a = airFluxY[i]; | |
double b = liqFluxY[i]; | |
double m = 0.5D * (airDensity * a + b); | |
int ix1 = x + 1 & xmax | y << shift; | |
int iy0 = x | (y - 1 & ymax) << shift; | |
int iy1 = x | (y + 1 & ymax) << shift; | |
int ixy = x + 1 & xmax | (y - 1 & ymax) << shift; | |
double px0 = m * velocityX[m <= 0.0D ? i : iy0]; | |
double px1 = m * velocityX[m <= 0.0D ? ix1 : ixy]; | |
double py0 = m * velocityY[m <= 0.0D ? i : iy0]; | |
double py1 = m * velocityY[m <= 0.0D ? iy1 : i]; | |
momentumX[iy0] -= px0; | |
momentumX[i] += px0; | |
momentumX[ixy] -= px1; | |
momentumX[ix1] += px1; | |
momentumY[iy0] -= py0; | |
momentumY[i] += py0 - py1; | |
momentumY[iy1] += py1; | |
x++; | |
i++; | |
} | |
} | |
i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
int ix = x + 1 & xmax | y << shift; | |
int iy = x | (y + 1 & ymax) << shift; | |
air[i] += ((airFluxX[i] - airFluxX[ix]) + airFluxY[i]) - airFluxY[iy]; | |
liq[i] += ((liqFluxX[i] - liqFluxX[ix]) + liqFluxY[i]) - liqFluxY[iy]; | |
x++; | |
i++; | |
} | |
} | |
} | |
public void applyMouse(double ox, double oy, double vx, double vy, double r) | |
{ | |
double v2 = vx * vx + vy * vy; | |
double r2 = r * r; | |
for(int y = 0; y < ymax; y++) | |
{ | |
for(int x = 0; x < xmax; x++) | |
{ | |
double dx = (double)x - ox; | |
double dy = (double)y - oy; | |
double d2 = dx * dx + dy * dy; | |
double dv = dx * vx + dy * vy; | |
if(dv > 0.0D) | |
if(dv < v2) | |
d2 -= (dv * dv) / v2; | |
else | |
d2 += v2 - 2D * dv; | |
if(d2 < r2) | |
{ | |
double w = d2 / r2; | |
int i0 = x | y << shift; | |
int ix = x + 1 & xmax | y << shift; | |
int iy = x | (y + 1 & ymax) << shift; | |
velocityX[i0] = w * velocityX[i0] + (1.0D - w) * vx; | |
velocityX[ix] = w * velocityX[ix] + (1.0D - w) * vx; | |
velocityY[i0] = w * velocityY[i0] + (1.0D - w) * vy; | |
velocityY[iy] = w * velocityY[iy] + (1.0D - w) * vy; | |
} | |
} | |
} | |
} | |
private synchronized void updateImage() | |
{ | |
value = 0.0D; | |
switch(imageType) | |
{ | |
case 118: // 'v' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double vx = 0.5D * (velocityX[i] + velocityX[x + 1 & xmax | y << shift]); | |
double vy = 0.5D * (velocityY[i] + velocityY[x | (y + 1 & ymax) << shift]); | |
pixels[i] = makePixel(vx, 0.86599999999999999D * vy - vx / 2D, -0.86599999999999999D * vy - vx / 2D); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 117: // 'u' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double px = 0.5D * (momentumX[i] + momentumX[x + 1 & xmax | y << shift]); | |
double py = 0.5D * (momentumY[i] + momentumY[x | (y + 1 & ymax) << shift]); | |
pixels[i] = makePixel(px, 0.86599999999999999D * py - px / 2D, -0.86599999999999999D * py - px / 2D); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 119: // 'w' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double w = ((velocityY[x + 1 & xmax | y << shift] - velocityY[x - 1 & xmax | y << shift]) + velocityX[x | (y + 1 & ymax) << shift]) - velocityX[x | (y - 1 & ymax) << shift]; | |
pixels[i] = makePixel(w, -w, 0.0D); | |
value += w; | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 115: // 's' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double s = ((velocityX[i] - velocityX[x + 1 & xmax | y << shift]) + velocityY[i]) - velocityY[x | (y + 1 & ymax) << shift]; | |
pixels[i] = makePixel(s, -s, 0.0D); | |
value += s; | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 120: // 'x' | |
{ | |
for(int i = 0; i < size; i++) | |
{ | |
double v = velocityX[i]; | |
pixels[i] = makePixel(v, -v, 0.0D); | |
value += momentumX[i]; | |
} | |
break; | |
} | |
case 121: // 'y' | |
{ | |
for(int i = 0; i < size; i++) | |
{ | |
double v = velocityY[i]; | |
pixels[i] = makePixel(v, -v, 0.0D); | |
value += momentumY[i]; | |
} | |
break; | |
} | |
case 112: // 'p' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double p = pressure.value[i]; | |
pixels[i] = makePixel(p, -p, 0.0D); | |
value += p; | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 101: // 'e' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double p = equalizer.value[i]; | |
pixels[i] = makePixel(p, -p, 0.0D); | |
value += p; | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 113: // 'q' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double p = equalizer.source[i]; | |
pixels[i] = makePixel(p, -p, 0.0D); | |
value += p; | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 97: // 'a' | |
{ | |
for(int i = 0; i < size; i++) | |
{ | |
double a = air[i]; | |
pixels[i] = makePixel(a, a, a); | |
value += a; | |
} | |
break; | |
} | |
case 98: // 'b' | |
{ | |
for(int i = 0; i < size; i++) | |
{ | |
double b = liq[i]; | |
pixels[i] = makePixel(b, b, b); | |
value += b; | |
} | |
break; | |
} | |
case 99: // 'c' | |
{ | |
for(int i = 0; i < size; i++) | |
{ | |
double r = room[i]; | |
double a = air[i]; | |
double b = liq[i]; | |
pixels[i] = makePixel(b, a, 1.0D - r); | |
value += b + a; | |
} | |
break; | |
} | |
case 109: // 'm' | |
{ | |
for(int i = 0; i < size; i++) | |
{ | |
double a = air[i]; | |
double b = liq[i]; | |
double m = airDensity * a + b; | |
pixels[i] = makePixel(m / 2D, m / 2D, m / 2D); | |
value += m; | |
} | |
break; | |
} | |
case 104: // 'h' | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double a = Math.min(air[i], 1.0D); | |
double b = Math.min(liq[i], 1.0D); | |
double g = Math.hypot(liq[x + 1 & xmax | y << shift] - liq[x - 1 & xmax | y << shift], liq[x | (y + 1 & ymax) << shift] - liq[x | (y - 1 & ymax) << shift]); | |
double s = Math.max(0.0D, Math.min(2D * a * b - 0.29999999999999999D * g, 1.0D)); | |
double h = (double)y / (double)ymax; | |
pixels[i] = makePixel((1.0D - s) * ((1.0D - b) * ((1.0D - h) * 0.90000000000000002D + h * 0.29999999999999999D) + b * ((1.0D - h) * 0.20000000000000001D + h * 0.10000000000000001D)) + s, (1.0D - s) * ((1.0D - b) * ((1.0D - h) * 0.80000000000000004D + h * 0.29999999999999999D) + b * ((1.0D - h) * 0.40000000000000002D + h * 0.20000000000000001D)) + s, (1.0D - s) * ((1.0D - b) * ((1.0D - h) * 0.69999999999999996D + h * 0.29999999999999999D) + b * ((1.0D - h) * 0.69999999999999996D + h * 0.40000000000000002D)) + s); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
case 100: // 'd' | |
case 102: // 'f' | |
case 103: // 'g' | |
case 105: // 'i' | |
case 106: // 'j' | |
case 107: // 'k' | |
case 108: // 'l' | |
case 110: // 'n' | |
case 111: // 'o' | |
case 114: // 'r' | |
case 116: // 't' | |
default: | |
{ | |
int i = 0; | |
for(int y = 0; y <= ymax; y++) | |
{ | |
for(int x = 0; x <= xmax;) | |
{ | |
double gx = liq[x + 1 & xmax | y << shift] - liq[x - 1 & xmax | y << shift]; | |
double gy = liq[x | (y + 1 & ymax) << shift] - liq[x | (y - 1 & ymax) << shift]; | |
double g2 = gx * gx + gy * gy; | |
double lx = x - xmax / 2; | |
double ly = y + ymax; | |
double l2 = lx * lx + ly * ly; | |
double gl = gx * lx + gy * ly; | |
double r = Math.min(g2, 1.0D); | |
double d = Math.min(2D * air[i] * liq[i], 1.0D); | |
double s = (0.5D * gl * gl) / ((g2 + 1.0D) * l2); | |
pixels[i] = makePixel((1.0D - d) * ((1.0D - r) * 0.5D + r * 0.29999999999999999D) + d + s, (1.0D - d) * ((1.0D - r) * 0.80000000000000004D + r * 0.59999999999999998D) + d + s, (1.0D - d) * ((1.0D - r) * 0.80000000000000004D + r * 0.59999999999999998D) + d + s); | |
x++; | |
i++; | |
} | |
} | |
break; | |
} | |
} | |
imageSource.newPixels(); | |
repaint(); | |
} | |
public synchronized void stop() | |
{ | |
thread.interrupt(); | |
} | |
public synchronized void destroy() | |
{ | |
removeMouseListener(this); | |
removeMouseMotionListener(this); | |
removeKeyListener(this); | |
} | |
public void mouseClicked(MouseEvent mouseevent) | |
{ | |
} | |
public void mouseEntered(MouseEvent mouseevent) | |
{ | |
} | |
public void mouseExited(MouseEvent mouseevent) | |
{ | |
} | |
public synchronized void mousePressed(MouseEvent e) | |
{ | |
lastMousePoint = e.getPoint(); | |
cursorX = lastMousePoint.x; | |
cursorY = lastMousePoint.y; | |
cursorVelocityX = 0.0D; | |
cursorVelocityY = 0.0D; | |
} | |
public synchronized void mouseReleased(MouseEvent e) | |
{ | |
lastMousePoint = null; | |
} | |
public synchronized void mouseDragged(MouseEvent e) | |
{ | |
lastMousePoint = e.getPoint(); | |
} | |
public void mouseMoved(MouseEvent mouseevent) | |
{ | |
} | |
public void keyPressed(KeyEvent keyevent) | |
{ | |
} | |
public void keyReleased(KeyEvent keyevent) | |
{ | |
} | |
public void keyTyped(KeyEvent e) | |
{ | |
char type = e.getKeyChar(); | |
if(type == ' ') | |
synchronized(this) | |
{ | |
Arrays.fill(velocityX, 0.0D); | |
Arrays.fill(velocityY, 0.0D); | |
Arrays.fill(momentumX, 0.0D); | |
Arrays.fill(momentumY, 0.0D); | |
} | |
else | |
if(type == imageType) | |
imageType = '\0'; | |
else | |
if('0' <= type && type <= '9') | |
reset(type - 48); | |
else | |
imageType = type; | |
} | |
public void update(Graphics g) | |
{ | |
paint(g); | |
} | |
public synchronized void paint(Graphics g) | |
{ | |
if(scale > 0) | |
{ | |
((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); | |
g.drawImage(image, 0, 0, getWidth(), getHeight(), this); | |
} else | |
{ | |
g.drawImage(image, 0, 0, this); | |
} | |
if(value != 0.0D) | |
{ | |
g.setColor(Color.white); | |
g.drawString(String.valueOf(value), 0, getHeight()); | |
} | |
} | |
private static int makePixel(double f1, double f2, double f3) | |
{ | |
int c1 = Math.max(0, Math.min((int)(255D * f1), 255)); | |
int c2 = Math.max(0, Math.min((int)(255D * f2), 255)); | |
int c3 = Math.max(0, Math.min((int)(255D * f3), 255)); | |
return 0xff000000 | c1 << 16 | c2 << 8 | c3; | |
} | |
static final long serialVersionUID = 0L; | |
private int scale; | |
private int xbits; | |
private int ybits; | |
private int xmax; | |
private int ymax; | |
private int shift; | |
private int size; | |
private double air[]; | |
private double liq[]; | |
private double room[]; | |
private double velocityX[]; | |
private double velocityY[]; | |
private double minVelocityX[]; | |
private double minVelocityY[]; | |
private double maxVelocityX[]; | |
private double maxVelocityY[]; | |
private double momentumX[]; | |
private double momentumY[]; | |
private double airBuffer[]; | |
private double liqBuffer[]; | |
private double airFluxX[]; | |
private double airFluxY[]; | |
private double liqFluxX[]; | |
private double liqFluxY[]; | |
private Grid pressure; | |
private Grid equalizer; | |
private double airDensity; | |
private double minMass; | |
private double equalizerBias; | |
private double gravityX; | |
private double gravityY; | |
private double tension; | |
private char imageType; | |
private int pixels[]; | |
private MemoryImageSource imageSource; | |
private Image image; | |
private double value; | |
private Point lastMousePoint; | |
private double cursorX; | |
private double cursorY; | |
private double cursorVelocityX; | |
private double cursorVelocityY; | |
private Thread thread; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment