private void InitializePlasticity()
        {
            _isPlasticityInitialized = true;

            _springs.Clear();
            foreach (Particle pa in Particles)
            {
                foreach (Particle pb in Particles)
                {
                    if (pa.GetHashCode() == pb.GetHashCode())
                    {
                        continue;
                    }

                    float q = pa.Position.dst(pb.Position);
                    _rij.Set(pb.Position);
                    _rij.Sub(pa.Position);
                    _rij.mul(1 / q);

                    if (q < RestLength)
                    {
                        _springs.Add(new Spring2(pa, pb, q));
                    }
                }
                pa.Velocity.Set(0, 0);
            }
        }
        private void ApplyViscosity(float deltaTime)
        {
            for (int i = 0; i < Particles.Count; i++)
            {
                Particle particle = Particles[i];

                _tempParticles = Particles.GetNearby(particle);

                int len2 = _tempParticles.Count;
                if (len2 > MaxNeighbors)
                {
                    len2 = MaxNeighbors;
                }

                for (int j = 0; j < len2; j++)
                {
                    Particle tempParticle = _tempParticles[j];

                    float q = particle.Position.dst2(tempParticle.Position);
                    if ((q < InfluenceRadiusSquared) && (q != 0))
                    {
                        q = (float)Math.Sqrt(q);
                        _rij.Set(tempParticle.Position);
                        _rij.Sub(particle.Position);
                        _rij.mul(1 / q);
                        q /= InfluenceRadius;

                        _tempVect.Set(particle.Velocity);
                        _tempVect.Sub(tempParticle.Velocity);
                        float u = _tempVect.dot(_rij);
                        if (u <= 0.0f)
                        {
                            continue;
                        }
                        float I = (deltaTime * (1 - q) * (ViscositySigma * u + ViscosityBeta * u * u));
                        _rij.mul(I * 0.5f);
                        _tempVect.Set(particle.Velocity);
                        _tempVect.Sub(_rij);
                        particle.Velocity.Set(_tempVect);
                        _tempVect.Set(tempParticle.Velocity);
                        _tempVect.add(_rij);
                        tempParticle.Velocity.Set(_tempVect);
                    }
                }
            }
        }
        private void DoubleDensityRelaxation()
        {
            for (int i = 0; i < Particles.Count; i++)
            {
                Particle particle = Particles[i];
                particle.Density     = 0;
                particle.NearDensity = 0;

                _tempParticles = Particles.GetNearby(particle);

                int len2 = _tempParticles.Count;
                if (len2 > MaxNeighbors)
                {
                    len2 = MaxNeighbors;
                }

                for (int j = 0; j < len2; j++)
                {
                    Particle tempParticle = _tempParticles[j];

                    float q = particle.Position.dst2(tempParticle.Position);
                    if (q < InfluenceRadiusSquared && q != 0)
                    {
                        q  = (float)Math.Sqrt(q);
                        q /= InfluenceRadius;
                        float qq = ((1 - q) * (1 - q));
                        particle.Density     += qq;
                        particle.NearDensity += qq * (1 - q);
                    }
                }

                particle.Pressure     = (Stiffness * (particle.Density - DensityRest));
                particle.NearPressure = (StiffnessNear * particle.NearDensity);
                _dx.Set(0.0f, 0.0f);

                for (int j = 0; j < len2; j++)
                {
                    Particle tempParticle = _tempParticles[j];

                    float q = particle.Position.dst2(tempParticle.Position);
                    if ((q < InfluenceRadiusSquared) && (q != 0))
                    {
                        q = (float)Math.Sqrt(q);
                        _rij.Set(tempParticle.Position);
                        _rij.Sub(particle.Position);
                        _rij.mul(1 / q);
                        q /= InfluenceRadius;

                        float D = (_deltaTime2 * (particle.Pressure * (1 - q) + particle.NearPressure * (1 - q) * (1 - q)));
                        _rij.mul(D * 0.5f);
                        tempParticle.Position.Set(tempParticle.Position.X + _rij.X, tempParticle.Position.Y + _rij.Y);
                        _dx.Sub(_rij);
                    }
                }
                particle.Position.Set(particle.Position.add(_dx));
            }
        }