Jump to content
  • Advertisement
Sign in to follow this  
trs79

[solved] SPH fluids "boiling", not colliding properly?

This topic is 2552 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all,

I'm seeing some strange behavior from some SPH fluid code I'm working on. I modified it to have a cylinder as a container/collision shape and that works fine. However, I then change it so that it slopes inward as it gets taller, and the particles start to move around constantly like the fluid is boiling and they never settle down. Also, the fluid level doesn't get higher as the container slopes inward as I'd expect. See image:

[attachment=6419:fluid.gif]

Here is the code I'm using to calculate positions (it's a modified form of the code at http://www.rchoetzle...hics/fluids.htm)



accel = p->sph_force;
accel *= m_Param[SPH_PMASS];
.....
// p is the particle structure, with z being up
// radius is the particle radius
// norm is a 3-vector

float boundary = abs((-.4 * p->pos.z) + 9.8);

diff = 2.0f * radius - (boundary - (float)fastSqrt_2(p->pos.x*p->pos.x + p->pos.y*p->pos.y)) * ss;

if (((diff < 8 *radius) && (diff > EPSILON)))
{
norm.Set ( -p->pos.x, -p->pos.y, 0 );
norm.Normalize();

adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
}

....

// Leapfrog Integration ----------------------------
vnext = accel;
vnext *= m_DT;
vnext += p->vel; // v(t+1/2) = v(t-1/2) + a(t) dt
p->vel_eval = p->vel;
p->vel_eval += vnext;
p->vel_eval *= 0.5; // v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5 used to compute forces later
p->vel = vnext;
vnext *= m_DT/ss;
p->pos += vnext; // p(t+1) = p(t) + v(t+1/2) dt



I'm pretty sure the way the normal is being added to the acceleration is causing the "boiling" of the particles, but I'm not sure. Thanks for any help

Share this post


Link to post
Share on other sites
Advertisement
Here I am assuming the norm variable holds the normal vector of the container, which would indicate to me that it needs to have a non-zero z value if the container is a frustrum instead of a cylinder.

Share this post


Link to post
Share on other sites

Here I am assuming the norm variable holds the normal vector of the container, which would indicate to me that it needs to have a non-zero z value if the container is a frustrum instead of a cylinder.


Thanks for the reply, you are correct the norm variable holds the normal vector of the container. Unfortunately when I change it to have a non-zero z value I still get the erratic particle movement, i.e :


norm.Set ( -p->pos.x, -p->pos.y, p->pos.z );
norm.Normalize();


Maybe I need something different for the z value?

Share this post


Link to post
Share on other sites
do you understand what the normal to a surface means?

you've been calculating the normal from the particle position, which is a little strange but I guess it works if you know the centre of the cylinder is at (0,0).

[font="Arial"]The equation for a cone with it's apex at the origin and axis parallel to z with aperture 2? is:
f(u) = u.z - |u|.cos ? = 0

Since your cone won't have it's apex at the origin, you can simply offset u.z by -h for apex at height 'h'.

Letting d = sqrt(x[sup]2[/sup]+y[sup]2[/sup]+(z-h)[sup]2[/sup])
the partial derivatives of f(u+h.z) are:
pf/px = -(x/d).cos ?, pf/py = -(y/d).cos ?, pf/pz = 1 - ((z-h)/d).cos ?

which are the components of your normal (to be normalised)[/font]


you can speed up the normalisation as we can determine the magnitude of the vector (pf/px, pf/py, pf/pz) to be sin [font=Arial][size=2]? as long as you know the point is on the surface of the cone[/font]

Share this post


Link to post
Share on other sites

do you understand what the normal to a surface means?

I do, but this is my first attempt at coding collision detection, probably why I got confused on the implementation :(

Thanks for the help, it was the z component that was causing problems, I finally ended up using this based on your code:

norm.Set ( -p->pos.x/diff, -p->pos.y/diff, 1.0-(p->pos.z/diff) );


along with the initial boundary slope code:
float boundary = abs((-.4 * p->pos.z) + 9.8);

Thanks again!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!