Water simulation updating asymetrically

Hey

So I have been working on simulation of water in 2 dimensions. It is comprised of nodes that are attached by “springs” to their neighbors and to the “water level”. it works fine, but it behaves differently on either side of a perturbation. I understand why, I think the updating is working twice on the next element in line (or something like that) and is effectively causing extra drag on one side. I tried some naive solutions but nothing has worked. any input is appreciated!

int num_of_springs = 101;
Spring[] springs = new Spring[num_of_springs];

void setup() {
  size(1200, 640);
  fill(255, 126);

  for (int i = 0; i<=springs.length-1; i++) {
    springs[i] = new Spring(i*width/num_of_springs+20, height/2, 0, 80, .99, 0.99); //(xpos, ypos, gravity, mass, damping, spring_constant)
  }
}

void draw() {
  background(0);
  line(0, height/2, width, height/2);

  for (int i = 0; i<=springs.length-1; i++) {
    if (i==0) {
      springs[0].update(springs[0].x, springs[1].y);
      springs[0].update(springs[0].x, height/2);
    } else if (i==springs.length-1) {
      springs[springs.length-1].update(springs[springs.length-1].x, springs[springs.length-2].y);
      springs[springs.length-1].update(springs[springs.length-1].x, height/2);
    } else {
      springs[i].update(springs[i-1].x, springs[i-1].y);
      springs[i].update(springs[i+1].x, springs[i+1].y);
      springs[i].update(springs[i].x, height/2);
    }
    springs[i].display();
  }

  if (keyPressed) {
    if (key == ' ') {            
      springs[springs.length/2].vy = 10;
    }
  }
}


class Spring {
  float vx, vy; 
  float x, y; 
  float gravity = 0;
  float mass = 0;
  float spring_constant = 0;
  float damping = 0;
  float target_x;
  float target_y;

  Spring(float xpos, float ypos, float gravity, float mass, float damping, float spring_constant) {
    x = xpos;
    y = ypos;
    this.gravity = gravity;
    this.mass = mass;
    this.spring_constant = spring_constant;
    this.damping = damping;
  }

  void update(float target_x, float target_y) { 

    line(x, y, target_x, target_y);
    this.target_x=target_x;
    this.target_y=target_y;

    float forceX = (target_x - x) * spring_constant;
    float ax = forceX / mass;
    vx = damping * (vx + ax);
    x += vx;

    float forceY = (target_y - y) * spring_constant;
    forceY += gravity;
    float ay = forceY / mass;
    vy = damping * (vy + ay);
    y += vy;

    if (abs(vy) < 0.01) {
      vy = 0.0;
    }
    if (abs(vx) < 0.01) {
      vx = 0.0;
    }
  }

  void display() {
    fill(255, 100);
    stroke(255);
    line(x, y, target_x, target_y);
    ellipse(x, y, 10, 10 );
    noFill();
  }
}
1 Like

i haven’t a solution for you but i was wondering if you had seen this cool thread about mario style water there is a great implementation in the accepted answer which includes wave summing and such.

2 Likes

@hotfooted – nice – that thread also links to a JavaScript demo that is actually ProcessingJS-based

http://jsfiddle.net/phil_mcc/sXmpD/8/#run

1 Like

Hey,
I think You should probably store all your data two times:
One for the current frame and one for the next. Calculate the next one from the current one and at the end, when all computation is done, save the data for the next in the current one. This way you dont get already updated values in your new computations.