package com.sk89q.mapbook.Liquid; import java.util.ArrayList; import org.bukkit.maps.MapDrawer; public class LiquidTest { private ArrayList<ArrayList<Node>> grid; private int gsizeX; private int gsizeY; private ArrayList<Particle> particles; private ArrayList<Node> active; private Material water; int ParticlesX; int ParticlesY; public LiquidTest(int gsizeX, int gsizeY, int particlesX, int particlesY) { ParticlesX = particlesX; ParticlesY = particlesY; this.particles = new ArrayList<Particle>(); this.gsizeX = gsizeX; this.gsizeY = gsizeY; this.grid = new ArrayList<ArrayList<Node>>(); // Nodes this.active = new ArrayList<Node>(); // Nodes this.water = new Material(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); } public void init() { int i = 0, j = 0; this.grid = new ArrayList<ArrayList<Node>>(); for (i = 0; i < this.gsizeX; i++) { this.grid.add(new ArrayList<Node>()); for (j = 0; j < this.gsizeY; j++) { this.grid.get(i).add(new Node()); } } Particle p; for (i = 0; i < ParticlesX; i++) for (j = 0; j < ParticlesY; j++) { p = new Particle(this.water, i + 4, j + 4, 0.0f, 0.0f); this.particles.add(p); } } public void paint(MapDrawer mapDrawer) { ArrayList<Particle> particles = this.particles; int len = particles.size(); mapDrawer.setForeColor((byte)19); for (int pi = 0; pi < len; pi++) { Particle p = particles.get(pi); mapDrawer.drawLine((int) (4.0 * p.x), (int) (4.0 * p.y), (int) (4.0 * (p.x - p.u)), (int) (4.0 * (p.y - p.v)),1); } } public void simulate() { for (Node n : this.active) n.clear(); this.active.clear(); int i, j; double x, y, phi; double fx = 0.0f, fy = 0.0f; ArrayList<Particle> particles = this.particles; for (int pi = 0; pi < particles.size(); pi++) { Particle p = particles.get(pi); p.cx = (int) (p.x - 0.5); p.cy = (int) (p.y - 0.5); x = p.cx - p.x; p.px[0] = (0.5 * x * x + 1.5 * x + 1.125); p.gx[0] = (x + 1.5); x += 1.0; p.px[1] = (-x * x + 0.75); p.gx[1] = (-2.0 * x); x += 1.0; p.px[2] = (0.5 * x * x - 1.5 * x + 1.125); p.gx[2] = (x - 1.5); y = p.cy - p.y; p.py[0] = (0.5 * y * y + 1.5 * y + 1.125); p.gy[0] = (y + 1.5); y += 1.0; p.py[1] = (-y * y + 0.75); p.gy[1] = (-2.0 * y); y += 1.0; p.py[2] = (0.5 * y * y - 1.5 * y + 1.125); p.gy[2] = (y - 1.5); for (int i1 = 0; i1 < 3; i1++) { for (int j1 = 0; j1 < 3; j1++) { Node n = this.grid.get(p.cx + i1).get(p.cy + j1); if (!n.active) { this.active.add(n); n.active = true; } phi = p.px[i1] * p.py[j1]; n.m += phi * p.mat.m; n.d += phi; n.gx += p.gx[i1] * p.py[j1]; n.gy += p.px[i1] * p.gy[j1]; } } } double density, pressure, weight; Node n01, n02; Node n11, n12; int cx, cy; int cxi, cyi; double pdx, pdy; double C20, C02, C30, C03; double csum1, csum2; double C21, C31, C12, C13, C11; double u, u2, u3; double v, v2, v3; ArrayList<Particle> particles1 = this.particles; ArrayList<ArrayList<Node>> grid = this.grid; for (int pi = 0, ln = particles1.size(); pi < ln; pi++) { Particle p = particles1.get(pi); cx = (int) (p.x); cy = (int) (p.y); cxi = cx + 1; cyi = cy + 1; n01 = grid.get(cx).get(cy); n02 = grid.get(cx).get(cyi); n11 = grid.get(cxi).get(cy); n12 = grid.get(cxi).get(cyi); double n11d = n11.d; double n11gx = n11.gx; double n11gy = n11.gy; double n12d = n11.d; double n12gy = n12.gy; double n12gx = n12.gx; double n02d = n02.d; double n02gx = n02.gx; double n02gy = n02.gy; double n01d = n01.d; double n01gx = n01.gx; double n01gy = n01.gy; pdx = n11d - n01d; pdy = n02d - n01d; C20 = 3.0 * pdx - n11gx - 2.0 * n01gx; C02 = 3.0 * pdy - n02gy - 2.0 * n01gy; C30 = -2.0 * pdx + n11gx + n01gx; C03 = -2.0 * pdy + n02gy + n01gy; csum1 = n01d + n01gy + C02 + C03; csum2 = n01d + n01gx + C20 + C30; C21 = 3.0 * n12d - 2.0 * n02gx - n12gx - 3.0 * csum1 - C20; C31 = -2.0 * n12d + n02gx + n12gx + 2.0 * csum1 - C30; C12 = 3.0 * n12d - 2.0 * n11gy - n12gy - 3.0 * csum2 - C02; C13 = -2.0 * n12d + n11gy + n12gy + 2.0 * csum2 - C03; C11 = n02gx - C13 - C12 - n01gx; u = p.x - cx; u2 = u * u; u3 = u * u2; v = p.y - cy; v2 = v * v; v3 = v * v2; density = n01d + n01gx * u + n01gy * v + C20 * u2 + C02 * v2 + C30 * u3 + C03 * v3 + C21 * u2 * v + C31 * u3 * v + C12 * u * v2 + C13 * u * v3 + C11 * u * v; pressure = density - 1; if (pressure > 2.0) pressure = 2.0; fx = 0.0; fy = 0.0; if (p.x < 4.0) fx += p.mat.m * (4.0 - p.x); else if (p.x > this.gsizeX - 5) fx += p.mat.m * (this.gsizeX - 5 - p.x); if (p.y < 4.0) fy += p.mat.m * (4.0 - p.y); else if (p.y > this.gsizeY - 5) fy += p.mat.m * (this.gsizeY - 5 - p.y); for (int i11 = 0; i11 < 3; i11++) { for (int j11 = 0; j11 < 3; j11++) { Node n = grid.get(p.cx + i11).get(p.cy + j11); phi = p.px[i11] * p.py[j11]; n.ax += -((p.gx[i11] * p.py[j11]) * pressure) + fx * phi; n.ay += -((p.px[i11] * p.gy[j11]) * pressure) + fy * phi; } } } ArrayList<Node> active = this.active; for (int ni = 0, ln = active.size(); ni < ln; ni++) { Node n = active.get(ni); double nm = n.m; if (nm > 0.0) { n.ax /= nm; n.ay /= nm; n.ay += 0.03; } } double mu, mv; ArrayList<Particle> particles11 = this.particles; ArrayList<ArrayList<Node>> grid1 = this.grid; for (int pi = 0, ln = particles11.size(); pi < ln; pi++) { Particle p = particles11.get(pi); Node n; for (int i1 = 0; i1 < 3; i1++) { for (int j1 = 0; j1 < 3; j1++) { n = grid1.get(p.cx + i1).get(p.cy + j1); phi = p.px[i1] * p.py[j1]; p.u += phi * n.ax; p.v += phi * n.ay; } } mu = p.mat.m * p.u; mv = p.mat.m * p.v; for (int i1 = 0; i1 < 3; i1++) { for (int j1 = 0; j1 < 3; j1++) { n = grid1.get(p.cx + i1).get(p.cy + j1); phi = p.px[i1] * p.py[j1]; n.u += phi * mu; n.v += phi * mv; } } } ArrayList<Node> active1 = this.active; for (int ni = 0, ln = active1.size(); ni < ln; ni++) { Node n = active1.get(ni); double m = n.m; if (m > 0.0) { n.u /= m; n.v /= m; } } double gu, gv; ArrayList<Particle> particles111 = this.particles; for (int pi = 0, ln = particles111.size(); pi < ln; pi++) { Particle p = particles111.get(pi); gu = 0.0; gv = 0.0; for (int i2 = 0; i2 < 3; i2++) { for (int j1 = 0; j1 < 3; j1++) { Node n = grid1.get(p.cx + i2).get(p.cy + j1); phi = p.px[i2] * p.py[j1]; gu += phi * n.u; gv += phi * n.v; } } p.x += gu; p.y += gv; p.u += 1.0 * (gu - p.u); p.v += 1.0 * (gv - p.v); if (p.x < 1.0) { p.x = (1.0 + Math.random() * 0.01); p.u = 0.0; } else if (p.x > this.gsizeX - 2) { p.x = (this.gsizeX - 2 - Math.random() * 0.01); p.u = 0.0; } if (p.y < 1.0) { p.y = (1.0 + Math.random() * 0.01); p.v = 0.0; } else if (p.y > this.gsizeY - 2) { p.y = (this.gsizeY - 2 - Math.random() * 0.01); p.v = 0.0; } } } }