/** * 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(); }