public override void Merge(ObiActor actor, IObiConstraintsBatch other)
        {
            var batch = other as ObiShapeMatchingConstraintsBatch;
            var user  = actor as IShapeMatchingConstraintsUser;

            if (batch != null && user != null)
            {
                if (!user.shapeMatchingConstraintsEnabled)
                {
                    return;
                }

                int initialIndexCount = particleIndices.count;

                // shape matching constraint particle indices are not reordered when deactivating constraints,
                // so instead of using batch.activeConstraintCount, batch.constraintCount. We need all of them.
                int numActiveIndices = 0;
                for (int i = 0; i < batch.constraintCount; ++i)
                {
                    numActiveIndices += batch.numIndices[i];
                }

                particleIndices.ResizeUninitialized(initialIndexCount + numActiveIndices);
                firstIndex.ResizeUninitialized(m_ActiveConstraintCount + batch.activeConstraintCount);
                numIndices.ResizeUninitialized(m_ActiveConstraintCount + batch.activeConstraintCount);
                explicitGroup.ResizeUninitialized(m_ActiveConstraintCount + batch.activeConstraintCount);
                materialParameters.ResizeUninitialized((m_ActiveConstraintCount + batch.activeConstraintCount) * 5);

                restComs.ResizeUninitialized(m_ActiveConstraintCount + batch.activeConstraintCount);
                coms.ResizeUninitialized(m_ActiveConstraintCount + batch.activeConstraintCount);
                orientations.ResizeUninitialized(m_ActiveConstraintCount + batch.activeConstraintCount);
                lambdas.ResizeInitialized(m_ActiveConstraintCount + batch.activeConstraintCount);

                numIndices.CopyFrom(batch.numIndices, 0, m_ActiveConstraintCount, batch.activeConstraintCount);
                explicitGroup.CopyFrom(batch.explicitGroup, 0, m_ActiveConstraintCount, batch.activeConstraintCount);
                orientations.CopyReplicate(actor.actorLocalToSolverMatrix.rotation, m_ActiveConstraintCount, batch.activeConstraintCount);

                for (int i = 0; i < numActiveIndices; ++i)
                {
                    particleIndices[initialIndexCount + i] = actor.solverIndices[batch.particleIndices[i]];
                }

                for (int i = 0; i < batch.activeConstraintCount; ++i)
                {
                    firstIndex[m_ActiveConstraintCount + i] = batch.firstIndex[i] + initialIndexCount;
                    materialParameters[(m_ActiveConstraintCount + i) * 5]     = user.deformationResistance;
                    materialParameters[(m_ActiveConstraintCount + i) * 5 + 1] = user.plasticYield;
                    materialParameters[(m_ActiveConstraintCount + i) * 5 + 2] = user.plasticCreep;
                    materialParameters[(m_ActiveConstraintCount + i) * 5 + 3] = user.plasticRecovery;
                    materialParameters[(m_ActiveConstraintCount + i) * 5 + 4] = user.maxDeformation;
                }

                base.Merge(actor, other);
            }
        }