Example #1
0
        void CalcVelocity(Fluid fluid)
        {
            for (int i = 0, lim = fluid.Particles.Count; i < lim; i++)
            {
                Particle p = fluid.Particles[i];
                float fx = p.x;
                float fy = p.y;
                int cx = Math.Min(GWidth - 3, Math.Max(0, (int)(fx - 0.5f)));
                int cy = Math.Min(GHeight - 3, Math.Max(0, (int)(fy - 0.5f)));

                // Add grid acceleration to the particle velocities
                CellWeight weight = fluid.Weights[i];
                for (int y = 0; y < 3; y++)
                {
                    for (int x = 0; x < 3; x++)
                    {
                        GridCell cell = Grid[cy + y, cx + x];
                        float w = weight.w(x, y);

                        p.vx += w * cell.ax;
                        p.vy += w * cell.ay;
                    }
                }

                p.vx += GravityX;
                p.vy += GravityY;

                // Check new position and push away from distance field boundaries
                float nx = fx + p.vx;
                float ny = fy + p.vy;
                float d = SDF.SampleDistance(nx, ny);
                if (d < 1f)
                {
                    float dirx, diry;
                    SDF.SampleGradient(nx, ny, out dirx, out diry);
                    p.vx += (dirx) * (1f - d) * (float)(1f + rand.NextDouble() * 0.01f);
                    p.vy += (diry) * (1f - d) * (float)(1f + rand.NextDouble() * 0.01f);
                }

                // Update fluid specific velocity grid
                for (int y = 0; y < 3; y++)
                {
                    for (int x = 0; x < 3; x++)
                    {
                        float w = weight.w(x, y);

                        fluid.Grid[cy + y, cx + x].m += w;
                        fluid.Grid[cy + y, cx + x].vx += (w * p.vx);
                        fluid.Grid[cy + y, cx + x].vy += (w * p.vy);
                    }
                }

                fluid.Particles[i] = p;
            }

            // Average out the fluid velocity grid
            for (int y = 0, ylim = GHeight; y < ylim; y++)
            {
                for (int x = 0, xlim = GWidth; x < xlim; x++)
                {
                    //GridCell & cell = fluid.Grid[y, x];
                    float m = fluid.Grid[y, x].m;
                    if (m == 0f)
                        continue;
                    fluid.Grid[y, x].vx /= m;
                    fluid.Grid[y, x].vy /= m;
                }
            }
        }
Example #2
0
        public void UpdateParticles(Fluid fluid)
        {
            for (int i = 0, lim = fluid.Particles.Count; i < lim; i++)
            {
                Particle p = fluid.Particles[i];

                int cx = Math.Min(GWidth - 3, Math.Max(0, (int)(p.x - 0.5f)));
                int cy = Math.Min(GHeight - 3, Math.Max(0, (int)(p.y - 0.5f)));

                // Get interpolated velocity
                CellWeight weight = fluid.Weights[i];
                float vx = 0f, vy = 0f, tweight = 0f;
                for (int y = 0; y < 3; y++)
                {
                    for (int x = 0; x < 3; x++)
                    {
                        GridCell cell = fluid.Grid[cy + y, cx + x];
                        float w = weight.w(x, y);
                        vx += w * cell.vx;
                        vy += w * cell.vy;
                    }
                }

                // Update particle position, velocity
                p.x += MathHelper.Clamp(vx, -1, 1);
                p.y += MathHelper.Clamp(vy, -1, 1);

                p.vx += GridCoeff * (vx - p.vx);
                p.vy += GridCoeff * (vy - p.vy);

                // Resolve collisions, clamp positions, update velocities based on this
                float x0 = p.x;
                float y0 = p.y;

                float d = SDF.SampleDistance(x0, y0);
                if (d < 0f)
                {
                    float dx, dy;
                    SDF.SampleGradient(x0, y0, out dx, out dy);
                    x0 -= dx;
                    y0 -= dy;
                }

                x0 = Math.Min(Math.Max(x0, 1f), GWidth - 2f);
                y0 = Math.Min(Math.Max(y0, 1f), GHeight - 2f);
                p.x = x0;
                p.y = y0;

                //F**K!
                fluid.Particles[i] = p;
            }
        }
Example #3
0
        void CalcAccel(Fluid fluid)
        {
            for (int i = 0, lim = fluid.Particles.Count; i < lim; i++)
            {
                float fx = fluid.Particles[i].x;
                float fy = fluid.Particles[i].y;
                int cx = Math.Min(GWidth - 3, Math.Max(0, (int)(fx - 0.5f)));
                int cy = Math.Min(GHeight - 3, Math.Max(0, (int)(fy - 0.5f)));

                CellWeight weight = fluid.Weights[i];

                // Determine interpolated mass and velocity derivatives
                float dudx = 0f, dudy = 0f;
                float dvdx = 0f, dvdy = 0f;
                float mass = 10.0f;
                for (int y = 0; y < 3; y++)
                {
                    for (int x = 0; x < 3; x++)
                    {
                        float w = weight.w(x, y);
                        float dx = weight.dx(x, y);
                        float dy = weight.dy(x, y);

                        GridCell cell = Grid[cy + y, cx + x];

                        dudx += cell.vx * dx;
                        dudy += cell.vx * dy;
                        dvdx += cell.vy * dx;
                        dvdy += cell.vy * dy;
                        mass += cell.m * w;
                    }
                }

                float pressure = (fluid.Stiffness / Math.Max(1f, fluid.Density)) *
                    (mass - fluid.Density);

                // Add a bit of a pushing force near the collision boundaries
                float ax = 0f, ay = 0f;
                float d = SDF.SampleDistance(fx, fy);
                if (d < 3f)
                {
                    float dirx, diry;
                    SDF.SampleGradient(fx, fy, out dirx, out diry);
                    ax += dirx * (1f - (d / 3f));
                    ay += diry * (1f - (d / 3f));
                }

                // Update grid acceleration values
                for (int y = 0; y < 3; y++)
                {
                    for (int x = 0; x < 3; x++)
                    {
                        float w = weight.w(x, y);
                        float dx = weight.dx(x, y);
                        float dy = weight.dy(x, y);

                        Grid[cy + y, cx + x].ax += ax * w - dx * pressure - (dudx * dx + dudy * dy) * fluid.Viscosity * w;
                        Grid[cy + y, cx + x].ay += ay * w - dy * pressure - (dvdx * dx + dvdy * dy) * fluid.Viscosity * w;
                    }
                }
            }
        }
Example #4
0
        public Fluid InitGrid(Fluid fluid)
        {
            for (int i = 0, lim = fluid.Particles.Count; i < lim; i++)
            {
                Particle p = fluid.Particles[i];

                int cx = Math.Min(GWidth - 3, Math.Max(0, (int)(p.x - 0.5f)));
                int cy = Math.Min(GHeight - 3, Math.Max(0, (int)(p.y - 0.5f)));

                float u = (float)cx - p.x;
                float v = (float)cy - p.y;

                // Biquadratic interpolation weights along each axis
                fluid.Weights[i].SetValues(u, v);

                for (int y = 0; y < 3; y++)
                {
                    for (int x = 0; x < 3; x++)
                    {
                        float w = fluid.Weights[i].w(x, y);

                        Grid[cy + y, cx + x].m += w;
                        Grid[cy + y, cx + x].vx += p.vx * w;
                        Grid[cy + y, cx + x].vy += p.vy * w;
                    }
                }
            }

            return fluid;
        }