elastic string
@author
int FPS = 30;
int NODE_NUM = 100;
float GRAVITY = 1.0;
float K_SPRING = 10.0;
float K_DAMPING = 10.0;
PVector[] locs;
PVector[] vels;
float l;
void setup(){
size(640, 640);
frameRate(FPS);
noFill();
stroke(#F8FAD4);
strokeWeight(4);
locs = new PVector[NODE_NUM];
vels = new PVector[NODE_NUM];
float startW = 120;
float endW = 520;
for(int i = 0; i < NODE_NUM; i++){
float w = map(i, 0, NODE_NUM - 1, startW, endW);
float h = height / 4;
locs[i] = new PVector(w, h);
vels[i] = new PVector(0, 0);
}
l = (endW - startW) / (NODE_NUM - 1);
}
void draw(){
background(#007FB1);
beginShape();
for(int i = 0; i < NODE_NUM; i++){
vertex(locs[i].x, locs[i].y);
}
endShape();
PVector[] nextVels = new PVector[NODE_NUM];
for(int i = 1; i < NODE_NUM - 1; i++){
PVector springForceLeft = getSpringForce(i, i - 1);
PVector springForceRight = getSpringForce(i, i + 1);
PVector dampingForceLeft = getDampingForce(i, i - 1);
PVector dampingForceRight = getDampingForce(i, i + 1);
PVector gravityForce = getGravityForce(i);
PVector force = new PVector(0, 0);
force.add(springForceLeft);
force.add(springForceRight);
force.add(dampingForceRight);
force.add(dampingForceLeft);
force.add(gravityForce);
PVector acc = PVector.mult(force, 1.0 / FPS);
PVector nextVel = PVector.add(vels[i], acc);
nextVels[i] = nextVel;
}
for(int i = 1; i < NODE_NUM - 1; i++){
vels[i] = nextVels[i];
locs[i].add(vels[i]);
}
}
PVector getSpringForce(int i, int j){
PVector locDiff = PVector.sub(locs[j], locs[i]);
PVector force = PVector.mult(locDiff, K_SPRING * (locDiff.mag() - l) / locDiff.mag());
if(j == 0 || j == NODE_NUM - 1){
force.mult(0.5);
}
return force;
}
PVector getDampingForce(int i, int j){
PVector velDiff = PVector.sub(vels[j], vels[i]);
PVector force = PVector.mult(velDiff, K_DAMPING);
if(j == 0 || j == NODE_NUM - 1){
force.mult(0.5);
}
return force;
}
PVector getGravityForce(int i){
return new PVector(0, GRAVITY);
}