示例#1
0
        /**
         * Changes the length of the rope, adding or removing particles from its end as needed (as long as there are enough pooled particles
         * left). Since particles are added/removed to/from the end only, any existing particle data (masses, editor selection data) will
         * be preserved for existing particles when adding new ones.
         */
        public void ChangeLength(float newLength)
        {
            if (rope == null)
            {
                return;
            }

            // Clamp new length to sane limits:
            newLength = Mathf.Clamp(newLength, 0, (rope.TotalParticles - 1) * rope.InterparticleDistance);

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

            // get constraint batch:
            ObiDistanceConstraintBatch distanceBatch = rope.DistanceConstraints.GetFirstBatch();

            // calculate the change in rope length:
            float lengthChange = newLength - rope.RestLength;

            // calculate length change of current constraint:
            float constraintLengthChange = Mathf.Clamp(lengthChange, -distanceBatch.restLengths[constraint], rope.InterparticleDistance - distanceBatch.restLengths[constraint]);

            distanceBatch.restLengths[constraint] += constraintLengthChange;
            lengthChange -= constraintLengthChange;

            // figure out how many particles we need to add (or remove) and what length will remain after that:
            int   particleChange  = lengthChange > 0 ? Mathf.CeilToInt(lengthChange / rope.InterparticleDistance): Mathf.FloorToInt(lengthChange / rope.InterparticleDistance);
            float remainingLenght = ObiUtils.Mod(lengthChange, rope.InterparticleDistance);

            if (particleChange > 0)
            {
                particleChange = AddParticles(particleChange);

                // we cannot add any particles, so extend the segment as much as possible.
                if (particleChange == 0)
                {
                    remainingLenght = rope.InterparticleDistance;
                }

                // Add remaining lenght to the new constraint:
                constraint = rope.GetConstraintIndexAtNormalizedCoordinate(normalizedCoord);
                distanceBatch.restLengths[constraint] = remainingLenght;
            }
            else if (particleChange < 0)
            {
                particleChange = RemoveParticles(-particleChange);

                // we cannot remove any particles, so reduce the segment as much as possible:
                if (particleChange == 0)
                {
                    remainingLenght = 0;
                }

                // Add remaining lenght to the new constraint:
                constraint = rope.GetConstraintIndexAtNormalizedCoordinate(normalizedCoord);
                distanceBatch.restLengths[constraint] = remainingLenght;
            }

            distanceBatch.PushDataToSolver(rope.DistanceConstraints);

            // Update rest length:
            rope.RecalculateLenght();
        }