public override IObiConstraintsBatch Clone(IObiConstraints constraints) { var clone = new ObiStretchShearConstraintsBatch(constraints as ObiStretchShearConstraintsData, this); clone.particleIndices.ResizeUninitialized(particleIndices.count); clone.orientationIndices.ResizeUninitialized(orientationIndices.count); clone.restLengths.ResizeUninitialized(restLengths.count); clone.restOrientations.ResizeUninitialized(restOrientations.count); clone.stiffnesses.ResizeUninitialized(stiffnesses.count); clone.particleIndices.CopyFrom(particleIndices); clone.orientationIndices.CopyFrom(orientationIndices); clone.restLengths.CopyFrom(restLengths); clone.restOrientations.CopyFrom(restOrientations); clone.stiffnesses.CopyFrom(stiffnesses); return(clone); }
protected virtual IEnumerator CreateStretchShearConstraints(List <Vector3> particleNormals) { stretchShearConstraintsData = new ObiStretchShearConstraintsData(); stretchShearConstraintsData.AddBatch(new ObiStretchShearConstraintsBatch()); stretchShearConstraintsData.AddBatch(new ObiStretchShearConstraintsBatch()); // rotation minimizing frame: ObiPathFrame frame = new ObiPathFrame(); frame.Reset(); for (int i = 0; i < totalParticles - 1; i++) { var batch = stretchShearConstraintsData.batches[i % 2] as ObiStretchShearConstraintsBatch; Vector2Int indices = new Vector2Int(i, i + 1); Vector3 d = positions[indices.y] - positions[indices.x]; restLengths[i] = d.magnitude; frame.Transport(positions[indices.x], d.normalized, 0); orientations[i] = Quaternion.LookRotation(frame.tangent, particleNormals[indices.x]); restOrientations[i] = orientations[i]; // Also set the orientation of the next particle. If it is not the last one, we will overwrite it. // This makes sure that open rods provide an orientation for their last particle (or rather, a phantom segment past the last particle). orientations[indices.y] = orientations[i]; restOrientations[indices.y] = orientations[i]; batch.AddConstraint(indices, indices.x, restLengths[i], Quaternion.identity); batch.activeConstraintCount++; if (i % 500 == 0) { yield return(new CoroutineJob.ProgressInfo("ObiRod: generating structural constraints...", i / (float)(totalParticles - 1))); } } // if the path is closed, add the last, loop closing constraint to a new batch to avoid sharing particles. if (path.Closed) { var loopClosingBatch = new ObiStretchShearConstraintsBatch(); stretchShearConstraintsData.AddBatch(loopClosingBatch); Vector2Int indices = new Vector2Int(m_ActiveParticleCount - 1, 0); Vector3 d = positions[indices.y] - positions[indices.x]; restLengths[m_ActiveParticleCount - 2] = d.magnitude; frame.Transport(positions[indices.x], d.normalized, 0); orientations[m_ActiveParticleCount - 1] = Quaternion.LookRotation(frame.tangent, particleNormals[indices.x]); restOrientations[m_ActiveParticleCount - 1] = orientations[m_ActiveParticleCount - 1]; loopClosingBatch.AddConstraint(indices, indices.x, restLengths[m_ActiveParticleCount - 2], Quaternion.identity); loopClosingBatch.activeConstraintCount++; } // Recalculate rest length: m_RestLength = 0; foreach (float length in restLengths) { m_RestLength += length; } }
public ObiStretchShearConstraintsBatch(ObiStretchShearConstraintsData constraints = null, ObiStretchShearConstraintsBatch source = null) : base(source) { m_Constraints = constraints; }
public ObiStretchShearConstraintsBatch(ObiStretchShearConstraintsBatch source = null) : base(source) { }