Пример #1
0
        private int AddParticles(int amount)
        {
            // get constraint batches:
            ObiDistanceConstraintBatch distanceBatch = rope.DistanceConstraints.GetFirstBatch();
            ObiBendConstraintBatch     bendingBatch  = rope.BendingConstraints.GetFirstBatch();

            amount = Mathf.Min(amount, rope.PooledParticles);

            // if no particles can be added, just return.
            if (amount == 0)
            {
                return(0);
            }

            // find current constraint and hot constraint:
            int constraint = rope.GetConstraintIndexAtNormalizedCoordinate(normalizedCoord);

            rope.DistanceConstraints.RemoveFromSolver(null);
            rope.BendingConstraints.RemoveFromSolver(null);

            // find indices of first N inactive particles. we'll need them to create new rope.
            // the first and last particle indices in this array will be the ones in the current constraint.
            int[] newParticleIndices = new int[amount + 2];
            for (int i = 0, j = 0; i < amount && j < rope.TotalParticles; ++j)
            {
                if (!rope.active[j])
                {
                    newParticleIndices[i + 1] = j;
                    rope.active[j]            = true;
                    rope.invMasses[j]         = 1.0f / ObiRope.DEFAULT_PARTICLE_MASS;
                    ++i;
                }
            }

            // TODO: closed curves have a different amount of bend constraints!

            Vector4[] zeroVelocity = new Vector4[] { Vector4.zero };
            Vector4[] refPosition1 = new Vector4[1];
            Vector4[] refPosition2 = new Vector4[1];

            if (direction)
            {
                // fill first and last indices of the new particles array with the ones in the current constraint:
                newParticleIndices[0] = distanceBatch.springIndices[constraint * 2];
                newParticleIndices[newParticleIndices.Length - 1] = distanceBatch.springIndices[constraint * 2 + 1];

                // update normalized coord:
                normalizedCoord = constraint / (float)(distanceBatch.ConstraintCount + amount);

                Oni.GetParticlePositions(rope.Solver.OniSolver, refPosition1, 1, rope.particleIndices[newParticleIndices[0]]);
                Oni.GetParticlePositions(rope.Solver.OniSolver, refPosition2, 1, rope.particleIndices[newParticleIndices[newParticleIndices.Length - 1]]);

                // update constraints:
                distanceBatch.SetParticleIndex(constraint, newParticleIndices[newParticleIndices.Length - 2], ObiDistanceConstraintBatch.DistanceIndexType.First, rope.Closed);
                bendingBatch.SetParticleIndex(constraint, newParticleIndices[newParticleIndices.Length - 2], ObiBendConstraintBatch.BendIndexType.First, rope.Closed);
                bendingBatch.SetParticleIndex(constraint - 1, newParticleIndices[1], ObiBendConstraintBatch.BendIndexType.Second, rope.Closed);

                // add constraints and particles:
                for (int i = 1; i < newParticleIndices.Length - 1; ++i)
                {
                    Vector4[] pos = new Vector4[] { refPosition1[0] + (refPosition2[0] - refPosition1[0]) * i / (float)(newParticleIndices.Length - 1) * 0.5f };
                    Oni.SetParticlePositions(rope.Solver.OniSolver, pos, 1, rope.particleIndices[newParticleIndices[i]]);
                    Oni.SetParticleVelocities(rope.Solver.OniSolver, zeroVelocity, 1, rope.particleIndices[newParticleIndices[i]]);

                    int newConstraintIndex = constraint + i - 1;
                    distanceBatch.InsertConstraint(newConstraintIndex, newParticleIndices[i - 1], newParticleIndices[i], rope.InterparticleDistance, 0, 0);
                    bendingBatch.InsertConstraint(newConstraintIndex, newParticleIndices[i - 1], newParticleIndices[i + 1], newParticleIndices[i], 0, 0, 0);
                }
            }
            else
            {
                // fill first and last indices of the new particles array with the ones in the current constraint:
                newParticleIndices[0] = distanceBatch.springIndices[constraint * 2 + 1];
                newParticleIndices[newParticleIndices.Length - 1] = distanceBatch.springIndices[constraint * 2];

                // update normalized coord:
                normalizedCoord = (constraint + amount) / (float)(distanceBatch.ConstraintCount + amount);

                Oni.GetParticlePositions(rope.Solver.OniSolver, refPosition1, 1, rope.particleIndices[newParticleIndices[0]]);
                Oni.GetParticlePositions(rope.Solver.OniSolver, refPosition2, 1, rope.particleIndices[newParticleIndices[newParticleIndices.Length - 1]]);

                // update constraints:
                distanceBatch.SetParticleIndex(constraint, newParticleIndices[newParticleIndices.Length - 2], ObiDistanceConstraintBatch.DistanceIndexType.Second, rope.Closed);
                bendingBatch.SetParticleIndex(constraint, newParticleIndices[1], ObiBendConstraintBatch.BendIndexType.First, rope.Closed);
                bendingBatch.SetParticleIndex(constraint - 1, newParticleIndices[newParticleIndices.Length - 2], ObiBendConstraintBatch.BendIndexType.Second, rope.Closed);

                // add constraints and particles:
                for (int i = 1; i < newParticleIndices.Length - 1; ++i)
                {
                    Vector4[] pos = new Vector4[] { refPosition1[0] + (refPosition2[0] - refPosition1[0]) * i / (float)(newParticleIndices.Length - 1) * 0.5f };
                    Oni.SetParticlePositions(rope.Solver.OniSolver, pos, 1, rope.particleIndices[newParticleIndices[i]]);
                    Oni.SetParticleVelocities(rope.Solver.OniSolver, zeroVelocity, 1, rope.particleIndices[newParticleIndices[i]]);

                    distanceBatch.InsertConstraint(constraint + 1, newParticleIndices[i], newParticleIndices[i - 1], rope.InterparticleDistance, 0, 0);
                    bendingBatch.InsertConstraint(constraint, newParticleIndices[i + 1], newParticleIndices[i - 1], newParticleIndices[i], 0, 0, 0);
                }
            }

            rope.DistanceConstraints.AddToSolver(null);
            rope.BendingConstraints.AddToSolver(null);
            rope.PushDataToSolver(ParticleData.ACTIVE_STATUS);

            rope.UsedParticles += amount;

            rope.RegenerateRestPositions();

            return(amount);
        }
Пример #2
0
        /**
         * Removes a certain amount of particles and constraints from the rope, at the point and direction specified:
         */
        private int RemoveParticles(int amount)
        {
            // get constraint batches:
            ObiDistanceConstraintBatch distanceBatch = rope.DistanceConstraints.GetFirstBatch();
            ObiBendConstraintBatch     bendingBatch  = rope.BendingConstraints.GetFirstBatch();

            amount = Mathf.Min(amount, rope.UsedParticles - 2);

            // find current constraint and hot constraint:
            int constraint    = Mathf.Max(rope.GetConstraintIndexAtNormalizedCoordinate(normalizedCoord), firstConstraintId);
            int hotConstraint = FindHotConstraint(distanceBatch, constraint, amount);

            amount = Mathf.Min(amount, Mathf.Abs(hotConstraint - constraint));

            // if no particles can be removed, just return.
            if (amount == 0)
            {
                return(0);
            }

            rope.DistanceConstraints.RemoveFromSolver(null);
            rope.BendingConstraints.RemoveFromSolver(null);

            if (direction)
            {
                // update normalized coord:
                normalizedCoord = constraint / (float)(distanceBatch.ConstraintCount - amount);

                // update constraints:
                distanceBatch.SetParticleIndex(constraint, distanceBatch.springIndices[hotConstraint * 2 + 1], ObiDistanceConstraintBatch.DistanceIndexType.Second, rope.Closed);
                bendingBatch.SetParticleIndex(constraint - 1, distanceBatch.springIndices[hotConstraint * 2 + 1], ObiBendConstraintBatch.BendIndexType.Second, rope.Closed);
                bendingBatch.SetParticleIndex(hotConstraint, distanceBatch.springIndices[constraint * 2], ObiBendConstraintBatch.BendIndexType.First, rope.Closed);

                // remove constraints and particles:
                for (int i = constraint + amount; i > constraint; --i)
                {
                    rope.active[distanceBatch.springIndices[i * 2]] = false;
                    distanceBatch.RemoveConstraint(i);
                    bendingBatch.RemoveConstraint(i - 1);
                }
            }
            else
            {
                // update normalized coord:
                normalizedCoord = (constraint - amount) / (float)(distanceBatch.ConstraintCount - amount);

                // update constraint:
                distanceBatch.SetParticleIndex(constraint, distanceBatch.springIndices[hotConstraint * 2], ObiDistanceConstraintBatch.DistanceIndexType.First, rope.Closed);
                bendingBatch.SetParticleIndex(constraint, distanceBatch.springIndices[hotConstraint * 2], ObiBendConstraintBatch.BendIndexType.First, rope.Closed);
                bendingBatch.SetParticleIndex(hotConstraint - 1, distanceBatch.springIndices[constraint * 2 + 1], ObiBendConstraintBatch.BendIndexType.Second, rope.Closed);

                // remove constraints and particles:
                for (int i = constraint - 1; i >= constraint - amount; --i)
                {
                    rope.active[distanceBatch.springIndices[i * 2 + 1]] = false;
                    distanceBatch.RemoveConstraint(i);
                    bendingBatch.RemoveConstraint(i);
                }
            }

            rope.DistanceConstraints.AddToSolver(null);
            rope.BendingConstraints.AddToSolver(null);
            rope.PushDataToSolver(ParticleData.ACTIVE_STATUS);

            rope.UsedParticles -= amount;

            rope.RegenerateRestPositions();

            return(amount);
        }