266 lines
10 KiB
C#
266 lines
10 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// Whether particles in this actor colide with particles using the same phase value.
|
|
/// </summary>
|
|
public bool selfCollisions
|
|
{
|
|
get { return m_SelfCollisions; }
|
|
set { if (value != m_SelfCollisions) { m_SelfCollisions = value; SetSelfCollisions(m_SelfCollisions); } }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether this actor's stretch/shear constraints are enabled.
|
|
/// </summary>
|
|
public bool stretchShearConstraintsEnabled
|
|
{
|
|
get { return _stretchShearConstraintsEnabled; }
|
|
set { if (value != _stretchShearConstraintsEnabled) { _stretchShearConstraintsEnabled = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); } }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compliance of this actor's stretch/shear constraints, along their length.
|
|
/// </summary>
|
|
public float stretchCompliance
|
|
{
|
|
get { return _stretchCompliance; }
|
|
set { _stretchCompliance = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shearing compliance of this actor's stretch/shear constraints, along the first axis orthogonal to their length.
|
|
/// </summary>
|
|
public float shear1Compliance
|
|
{
|
|
get { return _shear1Compliance; }
|
|
set { _shear1Compliance = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shearing compliance of this actor's stretch/shear constraints, along the second axis orthogonal to their length.
|
|
/// </summary>
|
|
public float shear2Compliance
|
|
{
|
|
get { return _shear2Compliance; }
|
|
set { _shear2Compliance = value; SetConstraintsDirty(Oni.ConstraintType.StretchShear); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether this actor's bend/twist constraints are enabled.
|
|
/// </summary>
|
|
public bool bendTwistConstraintsEnabled
|
|
{
|
|
get { return _bendTwistConstraintsEnabled; }
|
|
set { if (value != _bendTwistConstraintsEnabled) { _bendTwistConstraintsEnabled = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Torsional compliance of this actor's bend/twist constraints along their length.
|
|
/// </summary>
|
|
public float torsionCompliance
|
|
{
|
|
get { return _torsionCompliance; }
|
|
set { _torsionCompliance = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bending compliance of this actor's bend/twist constraints along the first axis orthogonal to their length.
|
|
/// </summary>
|
|
public float bend1Compliance
|
|
{
|
|
get { return _bend1Compliance; }
|
|
set { _bend1Compliance = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bending compliance of this actor's bend/twist constraints along the second axis orthogonal to their length.
|
|
/// </summary>
|
|
public float bend2Compliance
|
|
{
|
|
get { return _bend2Compliance; }
|
|
set { _bend2Compliance = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Threshold for plastic behavior.
|
|
/// </summary>
|
|
/// Once bending goes above this value, a percentage of the deformation (determined by <see cref="plasticCreep"/>) will be permanently absorbed into the rod's rest shape.
|
|
public float plasticYield
|
|
{
|
|
get { return _plasticYield; }
|
|
set { _plasticYield = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Percentage of deformation that gets absorbed into the rest shape per second, once deformation goes above the <see cref="plasticYield"/> threshold.
|
|
/// </summary>
|
|
public float plasticCreep
|
|
{
|
|
get { return _plasticCreep; }
|
|
set { _plasticCreep = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether this actor's chain constraints are enabled.
|
|
/// </summary>
|
|
public bool chainConstraintsEnabled
|
|
{
|
|
get { return _chainConstraintsEnabled; }
|
|
set { if (value != _chainConstraintsEnabled) { _chainConstraintsEnabled = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); } }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tightness of this actor's chain constraints.
|
|
/// </summary>
|
|
/// Controls how much chain constraints are allowed to compress.
|
|
public float tightness
|
|
{
|
|
get { return _tightness; }
|
|
set { _tightness = value; SetConstraintsDirty(Oni.ConstraintType.Chain); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Average distance between consecutive particle centers in this rod.
|
|
/// </summary>
|
|
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<ObiStretchShearConstraintsBatch>;
|
|
if (dc == null || dc.batchCount < 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 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);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|