Exemplo n.º 1
0
    private void UpdateParticles(ref List <mParticle> particles, float dTime)
    {
        float r = Domain.xMax;
        float l = Domain.xMin;
        // Rectangle contains coordinates inverse on y
        float t = Domain.yMax;
        float b = Domain.yMin;

        for (int i = 0; i < particles.Count; i++)
        {
            mParticle particle = particles[i];
            // Update velocity + position using forces
            particle.Update(dTime);
            // Clip positions to domain space
            if (particle.Position.x < l)
            {
                particle.Position.x = l + Constants.SmallEpsilon;
            }
            else if (particle.Position.x > r)
            {
                particle.Position.x = r - Constants.SmallEpsilon;
            }
            if (particle.Position.y < b)
            {
                particle.Position.y = b + Constants.SmallEpsilon;
            }
            else if (particle.Position.y > t)
            {
                particle.Position.y = t - Constants.SmallEpsilon;
            }

            // Reset force
            particle.Force = Vector2.zero;
        }
    }
Exemplo n.º 2
0
 public void Emit(ref List <mParticle> particles, double dTime)
 {
     if (this.Enabled)
     {
         // Calc particle count based on frequency
         time += dTime;
         int nParts = (int)(this.Frequency * time);
         if (nParts > 0)
         {
             // Create Particles
             for (int i = 0; i < nParts; i++)
             {
                 // Calc velocity based on the distribution along the normalized direction
                 float   dist   = UnityEngine.Random.value * Distribution - Distribution * 0.5f;
                 Vector2 normal = new Vector2(Direction.y, -Direction.x);
                 normal = normal * dist;
                 Vector2 vel = Direction + normal;
                 vel.Normalize();
                 float velLen = UnityEngine.Random.value * (this.VelocityMax - this.VelocityMin) + this.VelocityMin;
                 vel = vel * velLen;
                 // Calc Oldpos (for right velocity) using simple euler
                 // oldPos = this.Position - vel * m_time;
                 Vector2   oldPos = this.Position - vel * (float)time;
                 mParticle p      = new mParticle();
                 p.Position    = Position;
                 p.PositionOld = oldPos;
                 p.Velocity    = vel;
                 p.Mass        = ParticleMass;
                 particles.Add(p);
             }
             // Reset time
             time = 0.0;
         }
     }
 }
Exemplo n.º 3
0
    public void GetNeighbourIndex(ref mParticle particle, out List <int> neighbours)
    {
        neighbours = null;
        int x_ori = GetGridIndexX(ref particle);
        int y_ori = GetGridIndexY(ref particle);

        for (int xOff = -1; xOff < 2; xOff++)
        {
            for (int yOff = -1; yOff < 2; yOff++)
            {
                // Own index
                // Neighbour index
                int x = x_ori + xOff;
                int y = y_ori + yOff;
                // Clamp
                if (x > -1 && x < this.Width && y > -1 && y < this.Height)
                {
                    if (m_grid[x] != null)
                    {
                        List <int> idxList = m_grid[x][y];
                        if (idxList != null)
                        {
                            // Return neighbours index

                            neighbours.AddRange(idxList);
                            return;
                        }
                    }
                }
            }
        }
    }
Exemplo n.º 4
0
    public void Refresh(ref List <mParticle> particles)
    {
        m_p    = particles;
        m_grid = null;
        m_grid = new List <int> [Width][];
        for (int i = 0; i < neightbors.Length; i++)
        {
            neightbors[i].Clear();
        }
        if (particles != null)
        {
            for (int i = 0; i < particles.Count; i++)
            {
                mParticle p          = particles[i];
                int       gridIndexX = GetGridIndexX(ref p);
                int       gridIndexY = GetGridIndexY(ref p);
                p.grid_index = new Vector2(gridIndexX, gridIndexY);
                // Add particle to list
                if (m_grid[gridIndexX] == null)
                {
                    m_grid[gridIndexX] = new List <int> [Height];
                }
                if (m_grid[gridIndexX][gridIndexY] == null)
                {
                    m_grid[gridIndexX][gridIndexY] = new List <int>();
                }
                m_grid[gridIndexX][gridIndexY].Add(i);
            }
        }
        for (int i = 0; i < particles.Count; i++)
        {
            for (int xOff = -1; xOff < 2; xOff++)
            {
                for (int yOff = -1; yOff < 2; yOff++)
                {
                    int x = (int)particles[i].grid_index.x + xOff;
                    int y = (int)particles[i].grid_index.y + yOff;
                    // Clamp
                    if (x > -1 && x < this.Width && y > -1 && y < this.Height)
                    {
                        if (m_grid[x] != null)
                        {
                            List <int> idxList = m_grid[x][y];
                            if (idxList != null)
                            {
                                // Return neighbours index

                                neightbors[i].AddRange(idxList);
                            }
                        }
                    }
                }
            }
        }
    }
Exemplo n.º 5
0
    private int GetGridIndexY(ref mParticle particle)
    {
        int gridIndexY = (int)((particle.Position.y - Constants.SimulationDomain.yMin) / CellSpace);

        // Clamp Y
        if (gridIndexY < 0)
        {
            gridIndexY = 0;
        }
        if (gridIndexY >= Height)
        {
            gridIndexY = Height - 1;
        }
        return(gridIndexY);
    }
Exemplo n.º 6
0
    private int GetGridIndexX(ref mParticle particle)
    {
        int gridIndexX = (int)((particle.Position.x - Constants.SimulationDomain.xMin) / CellSpace);

        // Clamp X
        if (gridIndexX < 0)
        {
            gridIndexX = 0;
        }
        if (gridIndexX >= Width)
        {
            gridIndexX = Width - 1;
        }
        return(gridIndexX);
    }
Exemplo n.º 7
0
    private void NoOverlapParticles(ref List <mParticle> particles, ref Grid grid)
    {
        float      minDist   = .5f * CellSpace;
        float      minDistSq = minDist * minDist;
        Vector2    dist;
        List <int> list;
        int        nIdx;

        for (int i = 0; i < particles.Count; i++)
        {
            mParticle p = particles[i];
            list = grid.GetNeighbourIndex(p, i);
            for (int j = 0; j < list.Count; j++)
            {
                nIdx = list[j];
                mParticle pn = particles[nIdx];
                if (p != pn)
                {
                    dist = pn.Position - p.Position;
                    float distLenSq = dist.sqrMagnitude;
                    if (distLenSq < minDistSq)
                    {
                        if (distLenSq > Constants.SmallEpsilon)
                        {
                            float distLen = (float)Math.Sqrt((double)distLenSq);
                            dist           = dist * 0.5f * (distLen - minDist) / distLen;
                            pn.Position    = pn.Position - dist;
                            pn.PositionOld = pn.PositionOld - dist;
                            p.Position     = p.Position + dist;
                            p.PositionOld  = p.PositionOld + dist;
                        }
                        else
                        {
                            float diff = 0.5f * minDist;
                            pn.Position.x    -= diff;
                            pn.PositionOld.y -= diff;
                            p.Position.x     += diff;
                            p.PositionOld.y  += diff;
                        }
                    }
                }
            }
        }
    }
Exemplo n.º 8
0
    public static List <mParticle> Create(int nParticles, float cellSpace, Rect domain, float particleMass)
    {
        List <mParticle> particles = new List <mParticle>(nParticles);
        // Init. Particle positions
        float x0 = domain.x + cellSpace;
        float x  = x0;
        float y  = domain.y;

        for (int i = 0; i < nParticles; i++)
        {
            if (x == x0)
            {
                y += cellSpace;
            }
            Vector2   pos = new Vector2(x, y);
            mParticle p   = new mParticle();
            p.Position    = pos;
            p.PositionOld = pos;
            p.Mass        = particleMass;
            particles.Add(p);
            x = x + cellSpace < domain.width ? x + cellSpace : x0;
        }
        return(particles);
    }
Exemplo n.º 9
0
    private void Forces(ref List <mParticle> particles, ref Grid grid, Vector2 globalForce)
    {
        Vector2    f, dist;
        float      scalar;
        List <int> list;
        int        nIdx;

        for (int i = 0; i < particles.Count; i++)
        {
            mParticle p = particles[i];
            // Add global force to every particle
            p.Force += globalForce;

            list = grid.GetNeighbourIndex(p, i);
            for (int j = 0; j < list.Count; j++)
            {
                nIdx = list[j];
                if (nIdx < i)
                {
                    mParticle pn = particles[nIdx];
                    if (pn.Density > Constants.SmallEpsilon && p != pn)
                    {
                        dist = p.Position - pn.Position;

                        // pressure

                        scalar    = pn.Mass * (p.Pressure + pn.Pressure) / (2.0f * pn.Density);
                        f         = SKPressure.CalculateGradient(ref dist);
                        f         = f * scalar;
                        p.Force  -= f;
                        pn.Force += f;

                        // viscosity
                        // f = particles[nIdx].Mass * ((particles[nIdx].Velocity - particles[i].Velocity) / particles[nIdx].Density) * WViscosityLap(ref dist) * Constants.VISC0SITY;

                        /*
                         * scalar = pn.Mass * this.SKViscosity.CalculateLaplacian(ref dist) * Viscosity * 1 / pn.Density;
                         +f = pn.Velocity - p.Velocity;
                         +f = f * scalar;
                         +p.Force += f;
                         +pn.Force -= f;*/
                        Vector2 velA  = p.Velocity;
                        float   dist2 = dist.sqrMagnitude;
                        if (dist2 < CellSpace2)
                        {                           // Particles are near enough to exchange velocity.
                            float   length  = Mathf.Sqrt(dist2);
                            Vector2 sepDir  = dist / length;
                            Vector2 velB    = pn.Velocity;
                            Vector2 velDiff = velA - velB;
                            float   velSep  = Vector2.Dot(velDiff, sepDir);

                            if (velSep < 0.0f)

                            {                                                                     // Particles are approaching.
                                float   infl         = 1.0f - length / CellSpace;
                                float   velSepA      = Vector2.Dot(velA, sepDir);                 // vel of pcl A along sep dir.
                                float   velSepB      = Vector2.Dot(velB, sepDir);                 // vel of pcl B along sep dir.
                                float   velSepTarget = (velSepA + velSepB) * 0.5f;                // target vel along sep dir.
                                float   diffSepA     = velSepTarget - velSepA;                    // Diff btw A's vel and target.
                                float   changeSepA   = Viscosity * diffSepA * infl;               // Amount of vel change to appl
                                Vector2 changeA      = changeSepA * sepDir;                       // Velocity change to apply.

                                p.Force += (changeA - Constants.Friction * p.Velocity) * p.Mass;  // Apply velocity change to A.

                                pn.Force -= (changeA - Constants.Friction * p.Velocity) * p.Mass; // Apply commensurate change to B.
                            }
                        }
                    }
                }
            }
        }
    }
Exemplo n.º 10
0
 public List <int> GetNeighbourIndex(mParticle particle, int index)
 {
     return(neightbors[index]);
 }