Fluid-Simulation-Monochrome/src/fluid64x64.c

176 lines
5.4 KiB
C

void advect64x64(fix* dye, fix* vx, fix* vy, fix* outx, fix* outy, fix* outz) {
for (int j = 1; j < H-1; j++) {
for (int i = 1; i < W-1; i++) {
int id = ID(i, j);
fix x = FIX(i) - fmul(dtRdx, vx[id]);
fix y = FIX(j) - fmul(dtRdx, vy[id]);
if (x < 0) x = 0;
else if (x > MAX_X) x = MAX_X;
if (y < 0) y = 0;
else if (y > MAX_Y) y = MAX_Y;
int x1 = UNFIX(x);
int y1 = UNFIX(y);
int x2 = x1 + 1;
int y2 = y1 + 1;
int tl = ID(x1, y1);
int tr = ID(x2, y1);
int bl = ID(x1, y2);
int br = ID(x2, y2);
fix s1 = ffrac(x);
fix s0 = ONE - s1;
fix t1 = ffrac(y);
fix t0 = ONE - t1;
outx[id] = fmul(s0, fmul(t0, vx[tl]) + fmul(t1, vx[bl])) +
fmul(s1, fmul(t0, vx[tr]) + fmul(t1, vx[br]));
outy[id] = fmul(s0, fmul(t0, vy[tl]) + fmul(t1, vy[bl])) +
fmul(s1, fmul(t0, vy[tr]) + fmul(t1, vy[br]));
outz[id] = fmul(s0, fmul(t0, dye[tl]) + fmul(t1, dye[bl])) +
fmul(s1, fmul(t0, dye[tr]) + fmul(t1, dye[br]));
}
}
}
void fluid_step64x64() {
// Advect the velocity field and the dye (27.7ms)
advect64x64(dye, vx, vy, tx, ty, tz);
// Swap the pointers
swap(vx, tx);
swap(vy, ty);
swap(dye, tz);
// Velocity boundary conditions (0.1ms)
for (int i = 0; i < W; i++) {
vy[ID(i, 0)] = -vy[ID(i, 1)];
vy[ID(i, H-1)] = -vy[ID(i, H-2)];
vx[ID(i, 0)] = vx[ID(i, 1)];
vx[ID(i, H-1)] = vx[ID(i, H-2)];
}
for (int j = 0; j < H; j++) {
vx[ID(0, j)] = -vx[ID(1, j)];
vx[ID(W-1, j)] = -vx[ID(W-2, j)];
vy[ID(0, j)] = vy[ID(1, j)];
vy[ID(W-1, j)] = vy[ID(W-2, j)];
}
// Calculate divergence & first pressure iteration (3.6ms)
for (int j = 1; j < H-1; j++) {
for (int i = 1; i < W-1; i++) {
div[ID(i, j)] = fmul(alphaHalfRdx, vx[ID(i+1,j)] - vx[ID(i-1, j)] + vy[ID(i, j+1)] - vy[ID(i, j-1)]);
p[ID(i, j)] = div[ID(i, j)] >> 2;
}
}
// Initial Pressure boundary conditions (0ms)
for (int i = 0; i < W; i++) {
p[ID(i, 0)] = p[ID(i, 1)];
p[ID(i, H-1)] = p[ID(i, H-2)];
}
for (int j = 0; j < H; j++) {
p[ID(0, j)] = p[ID(1, j)];
p[ID(W-1, j)] = p[ID(W-2, j)];
}
// Poisson pressure solver (20.8ms)
for (int k = 0; k < pressureIterations-1; k++) {
// Jacobi iteration (20.4ms)
for (int j = 1; j < H-1; j++) {
for (int i = 1; i < W-1; i++) {
int id = ID(i, j);
p[id] = (div[id] + p[ID(i-1, j)] + p[ID(i+1, j)] + p[ID(i, j-1)] + p[ID(i, j+1)]) >> 2;
}
}
// Pressure boundary conditions (0.4ms)
for (int i = 0; i < W; i++) {
p[ID(i, 0)] = p[ID(i, 1)];
p[ID(i, H-1)] = p[ID(i, H-2)];
}
for (int j = 0; j < H; j++) {
p[ID(0, j)] = p[ID(1, j)];
p[ID(W-1, j)] = p[ID(W-2, j)];
}
}
// Apply Forces
if (currentView == 0) {
int lastX = addX;
int lastY = addY;
if (keydown(KEY_LEFT)) { addX -= 1; if (addX < 1) addX = W-2; }
else if (keydown(KEY_RIGHT)) { addX += 1; if (addX > W-2) addX = 1; }
if (keydown(KEY_UP)) { addY -= 1; if (addY < 1) addY = H-2; }
else if (keydown(KEY_DOWN)) { addY += 1; if (addY > H-2) addY = 1; }
fix adx = FIX(addX - lastX);
fix ady = FIX(addY - lastY);
if (adx || ady) {
fix ddx = abs(adx);
fix ddy = abs(ady);
fix vdx = adx / 10;
fix vdy = ady / 10;
fix ddxy = ddx + ddy;
for (int j = addY-3; j < addY+3; j++) {
for (int i = addX-3; i < addX+3; i++) {
if (i<=0||j<=0||i>=W-1||j>=H-1) continue;
int id = ID(i, j);
fix dist = radius - FIX((addX-i)*(addX-i)+(addY-j)*(addY-j));
if (dist < 0) continue;
fix dyeD = fmul(dist, dyeIntensity);
fix velD = fmul(dist, velIntensity);
dye[id] = dye[id] + fmul(ddxy, dyeD);
if (dye[id] > maxDyeIntensity) dye[id] = maxDyeIntensity;
vx[id] = vx[id] + fmul(vdx, velD);
vy[id] = vy[id] + fmul(vdy, velD);
}
}
}
}
// Subtract pressure from velocity & Diffuse dye and velocity (3.4ms)
for (int j = 1; j < H-1; j++) {
for (int i = 1; i < W-1; i++) {
int id = ID(i, j);
vx[id] = fmul(vx[id] - fmul(halfRdx, p[ID(i+1, j)] - p[ID(i-1, j)]), velDiffusion);
vy[id] = fmul(vy[id] - fmul(halfRdx, p[ID(i, j+1)] - p[ID(i, j-1)]), velDiffusion);
}
}
// Draw dye to vram (3.1ms)
uint32_t *vram = gint_vram+4;
for (int j = 1; j < H-1; j++) {
uint32_t data = 0;
data = (data << 1);
for(int k = 1; k < 32; k++) {
int x = 32*0+k;
int id = ID(x, j);
dye[id] = fmul(dye[id], dyeDiffusion);
data = (data << 1) | (dye[id] > saturateTreshold || (dye[id] > emptyTreshold && (x+j)%2));
}
vram[0] = data;
data = 0;
for(int k = 0; k < 31; k++) {
int x = 32*1+k;
int id = ID(x, j);
dye[id] = fmul(dye[id], dyeDiffusion);
data = (data << 1) | (dye[id] > saturateTreshold || (dye[id] > emptyTreshold && (x+j)%2));
}
data = (data << 1);
vram[1] = data;
vram+=4;
}
}