I am attempting to make an elementary soft body engine in C++ using SDL2. It works by considering all the vertices of the soft body to be interconnected by springs of same length and rigidity (with the same spring constant k
and length natural_length
). To make it more realistic, I also introduced a damping constant c
.
However, I encountered a frustrating problem. I have been trying to debug it for past 6-7 hours but to no avail. The soft body encounters many strange bugs which I don't understand
- Firstly, the "soft body" is not at all "soft". It becomes a crumpled mess of points every time. I have tried calculating the force of neighbouring points instead only, but it still becomes a crumpled mess.
- The soft body flies up to the top corner (origin) every time even though I haven't implemented any external forces.
Both of these bugs are visible in this image -
The 2 following functions (they are in the same class as with all the variables, hence need not take in any arguments) are the actual simulation part of the code. (I have omitted the rest of the code as it is unnecessary.)
I used a vector
of SDL_Points
to store every point and a vector
of Vector
to store their velocities. If you are wondering what Vector
is, it is simply a struct
I created which simply has 2 float
members x
and y
.
The acceleratePoints()
function assigns velocity and position to each point and checkCollision()
well... checks for collisions with the walls of the window, which has width scr_w
and height scr_h
.
void acceleratePoints()
{
vector<SDL_Point> soft_body_copy=soft_body;
vector<Vector> velocity_copy=velocity;
for(int i=0;i<soft_body.size();++i)
{
for(int j=0;j<soft_body.size();++j)
{
if(i!=j)
{
Vector d={(soft_body[j].x-soft_body[i].x)/100.0,(soft_body[j].y-soft_body[i].y)/100.0};
float t=atan2(d.y,d.x);
float disp=fabs(magnitude(d))-natural_length/100.0;
velocity_copy[i].x+=(k*disp*cos(t))/10000.0;
velocity_copy[i].y+=(k*disp*sin(t))/10000.0;
velocity_copy[i].x-=c*velocity_copy[i].x/100.0;
velocity_copy[i].y-=c*velocity_copy[i].y/100.0;
soft_body_copy[i].x+=velocity_copy[i].x;
soft_body_copy[i].y+=velocity_copy[i].y;
}
}
soft_body=soft_body_copy;
velocity=velocity_copy;
}
}
void checkCollision()
{
for(int k=0;k<soft_body.size();++k)
{
if(soft_body[k].x>=scr_w||soft_body[k].x<=0)
{
velocity[k].x*=e;
soft_body[k].x=soft_body[k].x>scr_w/2?scr_w-1:1;
}
if(soft_body[k].y>=scr_h||soft_body[k].y<=0)
{
velocity[k].y*=e;
soft_body[k].y=soft_body[k].y>scr_h/2?scr_h-1:1;
}
}
}
The magnitude()
function returns the magnitude of a Vector
.
The values for coefficient of restitution e
, damping constant c
and spring constant k
, which I used for the image are 0.5, 10 and 100 respectively.
Thank you for taking the time to read this! Help would be greatly appreciated.
Edit
Here is the entire code if anyone wants to test it. You'll need SDL and a folder 'img' with a '.bmp' file in 'img/point.bmp'.