_xiaofang/xiaofang/Assets/Obi/Scripts/RopeAndRod/Actors/ObiRod.cs

266 lines
10 KiB
C#
Raw Normal View History

2024-12-18 02:18:45 +08:00
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);
}
}
}
}