protected override void RebuildElementsFromConstraintsInternal() { var dc = GetConstraintsByType(Oni.ConstraintType.StretchShear) as ObiConstraints <ObiStretchShearConstraintsBatch>; if (dc == null) { return; } int constraintCount = dc.batches[0].activeConstraintCount + dc.batches[1].activeConstraintCount; elements = new List <ObiStructuralElement>(constraintCount); for (int i = 0; i < constraintCount; ++i) { var batch = dc.batches[i % 2] as ObiStretchShearConstraintsBatch; int constraintIndex = i / 2; var e = new ObiStructuralElement(); e.particle1 = batch.particleIndices[constraintIndex * 2]; e.particle2 = batch.particleIndices[constraintIndex * 2 + 1]; e.restLength = batch.restLengths[constraintIndex]; elements.Add(e); } if (dc.batches.Count > 2) { var batch = dc.batches[2]; var e = new ObiStructuralElement(); e.particle1 = batch.particleIndices[0]; e.particle2 = batch.particleIndices[1]; e.restLength = batch.restLengths[0]; elements.Add(e); } }
public bool Tear(ObiStructuralElement element) { // don't allow splitting if there are no free particles left in the pool. if (activeParticleCount >= m_RopeBlueprint.particleCount) { return(false); } // Cannot split fixed particles: if (m_Solver.invMasses[element.particle1] == 0) { return(false); } // Or particles that have been already split. int index = elements.IndexOf(element); if (index > 0 && elements[index - 1].particle2 != element.particle1) { return(false); } element.particle1 = SplitParticle(element.particle1); return(true); }
public void UpdateCursor() { rope = GetComponent <ObiRope>(); m_CursorElement = null; if (rope.isLoaded) { float elmMu; m_CursorElement = rope.GetElementAt(cursorMu, out elmMu); } }
protected override void RebuildElementsFromConstraintsInternal() { var dc = GetConstraintsByType(Oni.ConstraintType.Distance) as ObiConstraints <ObiDistanceConstraintsBatch>; if (dc == null || dc.GetBatchCount() < 2) { return; } int constraintCount = dc.batches[0].activeConstraintCount + dc.batches[1].activeConstraintCount; elements = new List <ObiStructuralElement>(constraintCount); for (int i = 0; i < constraintCount; ++i) { var batch = dc.batches[i % 2] as ObiDistanceConstraintsBatch; int constraintIndex = i / 2; var e = new ObiStructuralElement(); e.particle1 = solverIndices[batch.particleIndices[constraintIndex * 2]]; e.particle2 = solverIndices[batch.particleIndices[constraintIndex * 2 + 1]]; e.restLength = batch.restLengths[constraintIndex]; e.tearResistance = 1; elements.Add(e); } // loop-closing element: if (dc.batches.Count > 2) { var batch = dc.batches[2]; var e = new ObiStructuralElement(); e.particle1 = solverIndices[batch.particleIndices[0]]; e.particle2 = solverIndices[batch.particleIndices[1]]; e.restLength = batch.restLengths[0]; e.tearResistance = 1; elements.Add(e); } }
public void UpdateRenderer(ObiActor actor) { using (m_UpdateChainRopeRendererChunksPerfMarker.Auto()) { var rope = actor as ObiRopeBase; // In case there are no link prefabs to instantiate: if (linkPrefabs.Count == 0) { return; } // Regenerate instances if needed: if (linkInstances == null || linkInstances.Count < rope.particleCount) { CreateChainLinkInstances(rope); } var blueprint = rope.blueprint; int elementCount = rope.elements.Count; float twist = -sectionTwist * elementCount * twistAnchor; //we will define and transport a reference frame along the curve using parallel transport method: frame.Reset(); frame.SetTwist(twist); int lastParticle = -1; for (int i = 0; i < elementCount; ++i) { ObiStructuralElement elm = rope.elements[i]; Vector3 pos = rope.GetParticlePosition(elm.particle1); Vector3 nextPos = rope.GetParticlePosition(elm.particle2); Vector3 linkVector = nextPos - pos; Vector3 tangent = linkVector.normalized; if (rope.blueprint.usesOrientedParticles) { frame.Transport(nextPos, tangent, rope.GetParticleOrientation(elm.particle1) * Vector3.up, twist); twist += sectionTwist; } else { frame.Transport(nextPos, tangent, sectionTwist); } if (linkInstances[i] != null) { linkInstances[i].SetActive(true); Transform linkTransform = linkInstances[i].transform; linkTransform.position = pos + linkVector * 0.5f; linkTransform.localScale = rope.GetParticleMaxRadius(elm.particle1) * 2 * linkScale; linkTransform.rotation = Quaternion.LookRotation(tangent, frame.normal); } lastParticle = elm.particle2; } for (int i = elementCount; i < linkInstances.Count; ++i) { if (linkInstances[i] != null) { linkInstances[i].SetActive(false); } } } }
public int particleIndex; /**< index of the particle being torn*/ public ObiRopeTornEventArgs(ObiStructuralElement element, int particle) { this.element = element; this.particleIndex = particle; }
public void ChangeLength(float newLength) { // clamp new length to sane limits: newLength = Mathf.Clamp(newLength, 0, (rope.blueprint.particleCount - 1) * rope.ropeBlueprint.interParticleDistance); // calculate the change in rope length: float lengthChange = newLength - rope.restLength; // remove: if (lengthChange < 0) { lengthChange = -lengthChange; while (lengthChange > m_CursorElement.restLength) { lengthChange -= m_CursorElement.restLength; int index = rope.elements.IndexOf(m_CursorElement); if (index >= 0) { // positive direction: if (direction) { RemoveParticleAt(rope.solver.particleToActor[m_CursorElement.particle2].indexInActor); rope.elements.RemoveAt(index); if (index < rope.elements.Count && rope.elements[index].particle1 == m_CursorElement.particle2) { rope.elements[index].particle1 = m_CursorElement.particle1; } m_CursorElement = rope.elements[index]; } else // negative direction: { RemoveParticleAt(rope.solver.particleToActor[m_CursorElement.particle1].indexInActor); rope.elements.RemoveAt(index); if (index > 0) { if (rope.elements[index - 1].particle2 == m_CursorElement.particle1) { rope.elements[index - 1].particle2 = m_CursorElement.particle2; } m_CursorElement = rope.elements[index - 1]; } else { m_CursorElement = rope.elements[0]; } } } } // the remaining length is subtracted from the current constraint: if (lengthChange > 0) { m_CursorElement.restLength = Mathf.Max(0, m_CursorElement.restLength - lengthChange); } } // add else { float lengthDelta = Mathf.Min(lengthChange, Mathf.Max(0, rope.ropeBlueprint.interParticleDistance - m_CursorElement.restLength)); // extend the current element, if possible: if (lengthDelta > 0) { m_CursorElement.restLength += lengthDelta; lengthChange -= lengthDelta; } // once the current element has been extended, see if we must add new elements: while (m_CursorElement.restLength + lengthChange > rope.ropeBlueprint.interParticleDistance) { // calculate added length: lengthDelta = Mathf.Min(lengthChange, rope.ropeBlueprint.interParticleDistance); lengthChange -= lengthDelta; if (direction) { // add new particle: int newParticleSolverIndex = AddParticleAt(rope.solver.particleToActor[m_CursorElement.particle1].indexInActor); // insert a new element: ObiStructuralElement newElement = new ObiStructuralElement(); newElement.restLength = lengthDelta; newElement.particle1 = m_CursorElement.particle1; newElement.particle2 = newParticleSolverIndex; m_CursorElement.particle1 = newParticleSolverIndex; int index = rope.elements.IndexOf(m_CursorElement); rope.elements.Insert(index, newElement); m_CursorElement = newElement; } else { // add new particle: int newParticleSolverIndex = AddParticleAt(rope.solver.particleToActor[m_CursorElement.particle2].indexInActor); // insert a new element: ObiStructuralElement newElement = new ObiStructuralElement(); newElement.restLength = lengthDelta; newElement.particle1 = newParticleSolverIndex; newElement.particle2 = m_CursorElement.particle2; m_CursorElement.particle2 = newParticleSolverIndex; int index = rope.elements.IndexOf(m_CursorElement); rope.elements.Insert(index + 1, newElement); m_CursorElement = newElement; } } // the remaining length is added to the current constraint: if (lengthChange > 0) { m_CursorElement.restLength += lengthChange; } } rope.RebuildConstraintsFromElements(); rope.RecalculateRestLength(); }