Blame water.c

9e0c72
9e0c72
#include <math.h></math.h>
9e0c72
#include <stdlib.h></stdlib.h>
9e0c72
#include <helianthus.h></helianthus.h>
9e0c72
9e0c72
9e0c72
#define SIZE 100
9e0c72
9e0c72
9e0c72
double matrix[3][2] = {
9e0c72
  { 5,  2 },
9e0c72
  { 5, -2 },
9e0c72
  { 0, -5 } };
9e0c72
9e0c72
double invMatrix[2][2] = {
9e0c72
  { 0.1 ,  0.1  },
9e0c72
  { 0.25, -0.25 } };
9e0c72
9e0c72
9e0c72
9e0c72
double grid[2][SIZE][SIZE];
9e0c72
int gridId = 0;
9e0c72
double simTm;
9e0c72
9e0c72
9e0c72
double calcX(double x, double y, double z)
9e0c72
  { return matrix[0][0]*x + matrix[1][0]*y + matrix[2][0]*z; }
9e0c72
double calcY(double x, double y, double z)
9e0c72
  { return matrix[0][1]*x + matrix[1][1]*y + matrix[2][1]*z; }
9e0c72
9e0c72
double calcBackX(double sx, double sy)
9e0c72
  { return invMatrix[0][0]*sx + invMatrix[1][0]*sy; }
9e0c72
double calcBackY(double sx, double sy)
9e0c72
  { return invMatrix[0][1]*sx + invMatrix[1][1]*sy; }
9e0c72
9e0c72
9e0c72
void drawBox(double x, double y, double z, double dx, double dy, double dz, unsigned int color) {
9e0c72
  saveState();
9e0c72
  double ch = colorGetHue(color);
9e0c72
  double cs = colorGetSaturation(color);
9e0c72
  double cv = colorGetValue(color);
9e0c72
9e0c72
  noStroke();
9e0c72
9e0c72
  fill(colorByHSV(ch, cs, cv*0.6));
9e0c72
  moveTo( calcX(x, y, z),
9e0c72
          calcY(x, y, z) );
9e0c72
  lineTo( calcX(x+dx, y, z),
9e0c72
          calcY(x+dx, y, z) );
9e0c72
  lineTo( calcX(x+dx, y, z+dz),
9e0c72
          calcY(x+dx, y, z+dz) );
9e0c72
  lineTo( calcX(x, y, z+dz),
9e0c72
          calcY(x, y, z+dz) );
9e0c72
  closePath();
9e0c72
9e0c72
9e0c72
  fill(colorByHSV(ch, cs, cv*0.8));
9e0c72
  moveTo( calcX(x+dx, y, z),
9e0c72
          calcY(x+dx, y, z) );
9e0c72
  lineTo( calcX(x+dx, y+dy, z),
9e0c72
          calcY(x+dx, y+dy, z) );
9e0c72
  lineTo( calcX(x+dx, y+dy, z+dz),
9e0c72
          calcY(x+dx, y+dy, z+dz) );
9e0c72
  lineTo( calcX(x+dx, y, z+dz),
9e0c72
          calcY(x+dx, y, z+dz) );
9e0c72
  closePath();
9e0c72
9e0c72
9e0c72
  fill(color);
9e0c72
  moveTo( calcX(x, y, z+dz),
9e0c72
          calcY(x, y, z+dz) );
9e0c72
  lineTo( calcX(x+dx, y, z+dz),
9e0c72
          calcY(x+dx, y, z+dz) );
9e0c72
  lineTo( calcX(x+dx, y+dy, z+dz),
9e0c72
          calcY(x+dx, y+dy, z+dz) );
9e0c72
  lineTo( calcX(x, y+dy, z+dz),
9e0c72
          calcY(x, y+dy, z+dz) );
9e0c72
  closePath();
9e0c72
9e0c72
9e0c72
  restoreState();
9e0c72
}
9e0c72
9e0c72
9e0c72
void setPoint(int i, int j, int size, double z) {
9e0c72
  for(int ii = -size; ii <= size; ++ii)
9e0c72
    for(int jj = -size; jj <= size; ++jj)
9e0c72
      if ( i + ii >= 0 && i + ii < SIZE
9e0c72
        && j + jj >= 0 && j + jj < SIZE
9e0c72
        && ii*ii + jj*jj <= size*(size + 1) )
9e0c72
          grid[0][i+ii][j+jj] = grid[1][i+ii][j+jj] = z;
9e0c72
}
9e0c72
9e0c72
9e0c72
void init() { }
9e0c72
9e0c72
9e0c72
void draw() {
9e0c72
  double w = windowGetWidth();
9e0c72
  double h = windowGetHeight();
9e0c72
  double tm = windowGetSeconds();
9e0c72
9e0c72
  saveState();
9e0c72
  translate(w/2, h/2);
9e0c72
9e0c72
  double smx = mouseTransformedX();
9e0c72
  double smy = mouseTransformedY();
9e0c72
  double mx = calcBackX(smx, smy);
9e0c72
  double my = calcBackY(smx, smy);
9e0c72
9e0c72
  if (keyWentDown("space"))
9e0c72
    setPoint(randomNumber(0, SIZE-1), randomNumber(0, SIZE-1), 2, (randomFloat() - 0.5)*10);
9e0c72
9e0c72
  double k = 1/sqrt(2);
9e0c72
  double dt = 0.01;
9e0c72
  if (fabs(simTm - tm) > 5) simTm = tm - dt/2;
9e0c72
  while(simTm < tm) {
9e0c72
    if (mouseDown("left") || mouseDown("right") || mouseDown("middle")) {
9e0c72
      int i = (int)floor(mx + SIZE*0.5);
9e0c72
      int j = (int)floor(my + SIZE*0.5);
9e0c72
      setPoint(i, j, 4, mouseDown("left") ? 20 : mouseDown("right") ? -20 : 0);
9e0c72
    }
9e0c72
9e0c72
    int prevId = gridId;
9e0c72
    gridId = 1 - gridId;
9e0c72
    for(int i = 0; i < SIZE; ++i) {
9e0c72
      for(int j = 0; j < SIZE; ++j) {
9e0c72
        double z = grid[prevId][i][j];
9e0c72
        double v = z - grid[gridId][i][j];
9e0c72
9e0c72
        double f = 0;
9e0c72
        double sum = 0;
9e0c72
        if (i > 0     ) { f += grid[prevId][i-1][j] - z; sum += 1; }
9e0c72
        if (i < SIZE-1) { f += grid[prevId][i+1][j] - z; sum += 1; }
9e0c72
        if (j > 0     ) { f += grid[prevId][i][j-1] - z; sum += 1; }
9e0c72
        if (j < SIZE-1) { f += grid[prevId][i][j+1] - z; sum += 1; }
9e0c72
        if (i > 0      && j > 0     ) { f += k*(grid[prevId][i-1][j-1] - z); sum += k; }
9e0c72
        if (i < SIZE-1 && j > 0     ) { f += k*(grid[prevId][i+1][j-1] - z); sum += k; }
9e0c72
        if (i > 0      && j < SIZE-1) { f += k*(grid[prevId][i-1][j+1] - z); sum += k; }
9e0c72
        if (i < SIZE-1 && j < SIZE-1) { f += k*(grid[prevId][i+1][j+1] - z); sum += k; }
9e0c72
        if (sum > 0) f /= sum;
9e0c72
9e0c72
        grid[gridId][i][j] = z + (v + 0.1*f)*0.99;
9e0c72
      }
9e0c72
    }
9e0c72
    simTm += dt;
9e0c72
  }
9e0c72
9e0c72
  for(int i = 0; i < SIZE; ++i)
9e0c72
    for(int j = SIZE-1; j >= 0; --j)
9e0c72
      drawBox( i - SIZE*0.5 - 0.5,
9e0c72
               j - SIZE*0.5 - 0.5,
9e0c72
               -50,
9e0c72
               1, 1, 50 + grid[gridId][i][j],
9e0c72
               COLOR_AQUA );
9e0c72
9e0c72
  restoreState();
9e0c72
9e0c72
  saveState();
9e0c72
  noFill();
9e0c72
  text(10, 10, "try left and right mouse buttons");
9e0c72
  restoreState();
9e0c72
}
9e0c72
9e0c72
9e0c72
int main() {
9e0c72
  windowSetTitle("Water");
9e0c72
  windowSetVariableFrameRate();
9e0c72
  windowSetResizable(TRUE);
9e0c72
  windowSetInit(&init);
9e0c72
  windowSetDraw(&draw);
9e0c72
  windowRun();
9e0c72
  return 0;
9e0c72
}