using UnityEngine; using System.Collections; using System.Collections.Generic; namespace Obi { [AddComponentMenu("Physics/Obi/Obi Rod", 881)] [ExecuteInEditMode] [DisallowMultipleComponent] public class ObiRod : ObiRopeBase, IStretchShearConstraintsUser, IBendTwistConstraintsUser, IChainConstraintsUser { [SerializeField] protected ObiRodBlueprint m_RodBlueprint; // distance constraints: [SerializeField] protected bool _stretchShearConstraintsEnabled = true; [SerializeField] protected float _stretchCompliance = 0; [SerializeField] protected float _shear1Compliance = 0; [SerializeField] protected float _shear2Compliance = 0; // bend constraints: [SerializeField] protected bool _bendTwistConstraintsEnabled = true; [SerializeField] protected float _torsionCompliance = 0; [SerializeField] protected float _bend1Compliance = 0; [SerializeField] protected float _bend2Compliance = 0; [SerializeField] [Range(0, 0.1f)] protected float _plasticYield = 0; [SerializeField] protected float _plasticCreep = 0; // chain constraints: [SerializeField] protected bool _chainConstraintsEnabled = true; [SerializeField] [Range(0, 1)] protected float _tightness = 1; /// /// Whether particles in this actor colide with particles using the same phase value. /// public bool selfCollisions { get { return m_SelfCollisions; } set { if (value != m_SelfCollisions) { m_SelfCollisions = value; SetSelfCollisions(m_SelfCollisions); } } } /// /// Whether this actor's stretch/shear constraints are enabled. /// public bool stretchShearConstraintsEnabled { get { return _stretchShearConstraintsEnabled; } set { if (value != _stretchShearConstraintsEnabled) { _stretchShearConstraintsEnabled = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); } } } /// /// Compliance of this actor's stretch/shear constraints, along their length. /// public float stretchCompliance { get { return _stretchCompliance; } set { _stretchCompliance = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); } } /// /// Shearing compliance of this actor's stretch/shear constraints, along the first axis orthogonal to their length. /// public float shear1Compliance { get { return _shear1Compliance; } set { _shear1Compliance = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); } } /// /// Shearing compliance of this actor's stretch/shear constraints, along the second axis orthogonal to their length. /// public float shear2Compliance { get { return _shear2Compliance; } set { _shear2Compliance = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); } } /// /// Whether this actor's bend/twist constraints are enabled. /// public bool bendTwistConstraintsEnabled { get { return _bendTwistConstraintsEnabled; } set { if (value != _bendTwistConstraintsEnabled) { _bendTwistConstraintsEnabled = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } } } /// /// Torsional compliance of this actor's bend/twist constraints along their length. /// public float torsionCompliance { get { return _torsionCompliance; } set { _torsionCompliance = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } } /// /// Bending compliance of this actor's bend/twist constraints along the first axis orthogonal to their length. /// public float bend1Compliance { get { return _bend1Compliance; } set { _bend1Compliance = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } } /// /// Bending compliance of this actor's bend/twist constraints along the second axis orthogonal to their length. /// public float bend2Compliance { get { return _bend2Compliance; } set { _bend2Compliance = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } } /// /// Threshold for plastic behavior. /// /// Once bending goes above this value, a percentage of the deformation (determined by ) will be permanently absorbed into the rod's rest shape. public float plasticYield { get { return _plasticYield; } set { _plasticYield = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } } /// /// Percentage of deformation that gets absorbed into the rest shape per second, once deformation goes above the threshold. /// public float plasticCreep { get { return _plasticCreep; } set { _plasticCreep = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } } /// /// Whether this actor's chain constraints are enabled. /// public bool chainConstraintsEnabled { get { return _chainConstraintsEnabled; } set { if (value != _chainConstraintsEnabled) { _chainConstraintsEnabled = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } } } /// /// Tightness of this actor's chain constraints. /// /// Controls how much chain constraints are allowed to compress. public float tightness { get { return _tightness; } set { _tightness = value; SetConstraintsDirty(Oni.ConstraintType.Chain); } } /// /// Average distance between consecutive particle centers in this rod. /// public float interParticleDistance { get { return m_RodBlueprint.interParticleDistance; } } public override ObiActorBlueprint sourceBlueprint { get { return m_RodBlueprint; } } public ObiRodBlueprint rodBlueprint { get { return m_RodBlueprint; } set { if (m_RodBlueprint != value) { RemoveFromSolver(); ClearState(); m_RodBlueprint = value; AddToSolver(); } } } protected override void OnValidate() { base.OnValidate(); SetConstraintsDirty(Oni.ConstraintType.BendTwist); SetupRuntimeConstraints(); } public override void LoadBlueprint(ObiSolver solver) { base.LoadBlueprint(solver); RebuildElementsFromConstraints(); SetupRuntimeConstraints(); } public override void RequestReadback() { base.RequestReadback(); solver.orientations.Readback(); } public override void SimulationEnd(float simulatedTime, float substepTime) { base.SimulationEnd(simulatedTime, substepTime); solver.orientations.WaitForReadback(); } private void SetupRuntimeConstraints() { SetConstraintsDirty(Oni.ConstraintType.StretchShear); SetConstraintsDirty(Oni.ConstraintType.BendTwist); SetConstraintsDirty(Oni.ConstraintType.Chain); SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); SetSelfCollisions(selfCollisions); RecalculateRestLength(); SetSimplicesDirty(); } public Vector3 GetBendTwistCompliance(ObiBendTwistConstraintsBatch batch, int constraintIndex) { return new Vector3(bend1Compliance, bend2Compliance, torsionCompliance); } public Vector2 GetBendTwistPlasticity(ObiBendTwistConstraintsBatch batch, int constraintIndex) { return new Vector2(plasticYield, plasticCreep); } public Vector3 GetStretchShearCompliance(ObiStretchShearConstraintsBatch batch, int constraintIndex) { return new Vector3(shear1Compliance, shear2Compliance, stretchCompliance); } protected override void RebuildElementsFromConstraintsInternal() { var dc = GetConstraintsByType(Oni.ConstraintType.StretchShear) as ObiConstraints; if (dc == null || dc.batchCount < 2) return; int constraintCount = dc.batches[0].activeConstraintCount + dc.batches[1].activeConstraintCount; elements = new List(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 = solverIndices[batch.particleIndices[constraintIndex * 2]]; e.particle2 = solverIndices[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 = solverIndices[batch.particleIndices[0]]; e.particle2 = solverIndices[batch.particleIndices[1]]; e.restLength = batch.restLengths[0]; elements.Add(e); } } } }