public void OnSceneGUI() { if (Event.current.type == EventType.Repaint) { ObiRope rope = cursor.GetComponent <ObiRope>(); ObiDistanceConstraintBatch distanceBatch = rope.DistanceConstraints.GetFirstBatch(); Handles.color = Color.yellow; int constraint = rope.GetConstraintIndexAtNormalizedCoordinate(cursor.normalizedCoord); Vector3 pos1 = rope.GetParticlePosition(distanceBatch.springIndices[constraint * 2]); Vector3 pos2 = rope.GetParticlePosition(distanceBatch.springIndices[constraint * 2 + 1]); if (cursor.direction) { Handles.DrawWireDisc(pos1, pos2 - pos1, rope.thickness * 2); Vector3 direction = pos2 - pos1; if (direction != Vector3.zero) { Handles.ArrowHandleCap(0, pos1, Quaternion.LookRotation(direction), 0.2f, EventType.Repaint); } } else { Handles.DrawWireDisc(pos2, pos1 - pos2, rope.thickness * 2); Vector3 direction = pos1 - pos2; if (direction != Vector3.zero) { Handles.ArrowHandleCap(0, pos2, Quaternion.LookRotation(direction), 0.2f, EventType.Repaint); } } } }
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); }