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);
                    }
                }
            }
        }
Exemple #2
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);
        }