Skip to content

Instantly share code, notes, and snippets.

@Nekodigi
Created March 7, 2020 15:03
Show Gist options
  • Save Nekodigi/a69d4c0d3b17058a9a958320fcc36f15 to your computer and use it in GitHub Desktop.
Save Nekodigi/a69d4c0d3b17058a9a958320fcc36f15 to your computer and use it in GitHub Desktop.
//based on this site https://github.com/smacke/pressure-softbody
float r = 10;
float grav = 1100;//gravity
float resolution = 30;
float dt = 0.01;
float mouseR = 200;
Softbody softbody;
void setup(){
fullScreen();
//size(500, 500);
softbody = new Softbody(r, resolution);
}
void draw(){
background(255);
fill(255, 0, 0);
softbody.update();
softbody.show();
ellipse(mouseX, mouseY, mouseR, mouseR);
}
class Vertex{
PVector pos;
PVector vel = new PVector();
PVector acc = new PVector();
Vertex(PVector pos){
this.pos = pos;
}
void update(){
acc.add(new PVector(0, grav));
vel.add(PVector.mult(acc, dt));
pos.add(PVector.mult(vel, dt));
if(pos.x < 0 || pos.x > width){
vel.x = -vel.x/2;
}
if(pos.y < 0 || pos.y > height){
vel.y = -vel.y/2;
}
PVector mouse = new PVector(mouseX, mouseY);
if(PVector.dist(pos, mouse) < mouseR/2){
float angle = atan2(pos.y-mouseY, pos.x-mouseX);println(angle);
pos = mouse.add(PVector.fromAngle(angle).setMag(mouseR/2));
vel.mult(-0.5);
}
pos = new PVector(constrain(pos.x, 0, width), constrain(pos.y, 0, height));
acc = new PVector();
}
}
class Softbody{
ArrayList<Vertex> vertices = new ArrayList<Vertex>();
ArrayList<Spring> springs = new ArrayList<Spring>();
float resolution;
float ks = 3000;//spring power
float kd = 35;//spring dump?
float r;
float pressure = 7000000;
float volume;
Softbody(float r, float resolution){
this.r = r;
this.resolution = resolution;
for(float i = 0; i < resolution; i++){
float theta = map(i, 0, resolution, 0, TWO_PI);
vertices.add(new Vertex(PVector.fromAngle(theta).setMag(r).add(new PVector(width/2, height/2))));
}
for(int i = 0; i < resolution; i++){
springs.add(new Spring(vertices.get(i), vertices.get((i+1)%int(resolution))));
}
}
void update(){
for(int i = 0; i < resolution; i++){
Spring spring = springs.get(i);
float l = spring.calcL();
if(l != 0){
PVector vSub = PVector.sub(spring.start.vel, spring.end.vel);
PVector pSub = PVector.sub(spring.start.pos, spring.end.pos);
float f = (l - spring.baseL) * ks + PVector.dot(vSub, pSub) * kd / l;
pSub.normalize();//spring direction
spring.start.acc.sub(PVector.mult(pSub, f));
spring.end.acc.add(PVector.mult(pSub, f));
spring.normal = pSub.rotate(HALF_PI);
}
}
volume = 0;
for(int i = 0; i < resolution; i++){
Spring spring = springs.get(i);
float l = spring.calcL();
float midX = (spring.start.pos.x - spring.end.pos.x)/2;
volume += abs(midX) * abs(spring.normal.x) * l;
}
for(int i = 0; i < resolution; i++){
Spring spring = springs.get(i);
float l = spring.calcL();
float pressureRev = l * pressure /volume;
spring.start.acc.add(PVector.mult(spring.normal, pressureRev));
spring.end.acc.add(PVector.mult(spring.normal, pressureRev));
}
for(Vertex v : vertices){
v.update();
}
}
void show(){
beginShape();
for(Vertex v : vertices){
vertex(v.pos.x, v.pos.y);
}
endShape();
}
}
class Spring{
Vertex start, end;
float baseL;
PVector normal;
Spring(Vertex start, Vertex end){
this.start = start;
this.end = end;
this.baseL = PVector.dist(start.pos, end.pos);
}
float calcL(){
return PVector.dist(start.pos, end.pos);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment