private List <Dictionary <int, ParticleInteraction> > GenerateParticleInteractions(int particleTypeCount)
        {
            var result             = new List <Dictionary <int, ParticleInteraction> >();
            var particleLifeConfig = (ParticleLifeConfig)spaceConfig;

            for (int i = 0; i < particleTypeCount; i++) // Loop every particle type
            {
                var interactions = new Dictionary <int, ParticleInteraction>();

                for (int j = 0; j < particleTypeCount; j++) // For every particle type, it has interaction with every other particle.
                {
                    var interaction = new ParticleInteraction()
                    {
                        GraphDots = new List <Vector2>()
                    };

                    for (int k = 0; k < particleLifeConfig.MinimumParticleInteractions.Count; k++) // Generate all graph dots...
                    {
                        var xVal = RNG.RandomFloat(particleLifeConfig.MinimumParticleInteractionDistances[k], particleLifeConfig.MaximumParticleInteractionDistances[k]);
                        var yVal = RNG.RandomFloat(particleLifeConfig.MinimumParticleInteractions[k], particleLifeConfig.MaximumParticleInteractions[k]);

                        interaction.GraphDots.Add(new Vector2(xVal, yVal));
                    }

                    interactions.Add(j, interaction); // Add to interactions
                }

                result.Add(interactions);
            }

            return(result);
        }
Exemple #2
0
    // UPDATE STEPS
    void SatisfyConstraints()
    {
        // Using a reverse loop allows us to safely remove constraints from the list
        for (int interactionIndex = particleInteractions.Count - 1; interactionIndex >= 0; interactionIndex--)
        {
            ParticleInteraction interaction = particleInteractions[interactionIndex];

            // Only satisfy constraints for enabled interactions
            if (!simulationManager.GetSpringForce(interaction.interactionType).enabled)
            {
                continue;
            }
            // If tearing, check how far apart the particles are and maybe remove them from the list
            if (constants.enableTearing)
            {
                float magnitude = (particles[interaction.particle1].Position - particles[interaction.particle2].Position).magnitude;
                if (magnitude > interaction.equilibriumDistance * constants.maxTearingRatio)
                {
                    particleInteractions.RemoveAt(interactionIndex);
                    // Don't satisfy this constraint, since they it's broken now
                    continue;
                }
            }

            SatisfyConstraint(interaction);
        }
    }
    // UPDATE STEPS
    void AddInternalForces()
    {
        for (int interactionIndex = particleInteractions.Count - 1; interactionIndex >= 0; interactionIndex--)
        {
            // Using a reverse loop allows us to safely remove items from the indices list
            ParticleInteraction interaction = particleInteractions[interactionIndex];
            SpringForceSettings springForceOfInteraction = simulationManager.GetSpringForce(interaction.interactionType);
            if (springForceOfInteraction.enabled)
            {
                EulerParticle particle1 = particles[interaction.particle1];
                EulerParticle particle2 = particles[interaction.particle2];

                Vector3 direction = particle1.Position - particle2.Position;
                float   magnitude = direction.magnitude;

                // Cloth ripping
                if (constants.enableTearing && magnitude > interaction.equilibriumDistance * constants.maxTearingRatio)
                {
                    // Break the connection (we could do the same for the reverse one). No force added.
                    particleInteractions.RemoveAt(interactionIndex);
                    continue;
                }

                Vector3 force        = direction / magnitude * (interaction.equilibriumDistance - magnitude) * springForceOfInteraction.forceConstant;
                Vector3 dampingForce = (particles[interaction.particle2].velocity - particles[interaction.particle1].velocity) * constants.springDampingConstant;

                particle1.AddForce(force + dampingForce);
            }
        }
    }
        public void TestInterpolation()
        {
            var left        = new Vector2(1, 2);
            var right       = new Vector2(4, 7);
            var searchPoint = 3.0f;

            var interaction = new ParticleInteraction();

            interaction.GraphDots = new List <Vector2>();

            interaction.GraphDots.Add(left);
            interaction.GraphDots.Add(right);

            Assert.AreEqual(interaction.GetInteraction(searchPoint),
                            (left.Y + ((searchPoint - left.X) / (right.X - left.X)) * (right.Y - left.Y))
                            );
        }
Exemple #5
0
    // CONSTRAINTS
    void SatisfyConstraint(ParticleInteraction interaction)
    {
        VerletParticle particle1 = particles[interaction.particle1];
        VerletParticle particle2 = particles[interaction.particle2];

        // Correction vector from particle1 -> particle2
        Vector3 directionVector  = particle2.Position - particle1.Position;
        Vector3 correctionVector = (1 - interaction.equilibriumDistance / directionVector.magnitude) * directionVector;

        // Apply half the correction to each particle (unless one is fixed)
        if (!particle1.isFixed && !particle2.isFixed)
        {
            particle1.Position += correctionVector / 2;
            particle2.Position -= correctionVector / 2;
        }
        else if (particle1.isFixed && !particle2.isFixed)
        {
            particle2.Position -= correctionVector;
        }
        else if (!particle1.isFixed && particle2.isFixed)
        {
            particle1.Position += correctionVector;
        }
    }