_xiaofang/xiaofang/Assets/Obi/Scripts/RopeAndRod/Actors/ObiRopeBase.cs
杨号敬 bcc74f0465 add
2024-12-18 02:18:45 +08:00

163 lines
5.9 KiB
C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Obi
{
public abstract class ObiRopeBase : ObiActor, IAerodynamicConstraintsUser
{
[SerializeField] protected bool m_SelfCollisions = false;
[HideInInspector] [SerializeField] protected float restLength_ = 0;
[HideInInspector] public List<ObiStructuralElement> elements = new List<ObiStructuralElement>(); /**< Elements.*/
public event ActorCallback OnElementsGenerated;
// aerodynamics
[SerializeField] protected bool _aerodynamicsEnabled = true;
[SerializeField] protected float _drag = 0.05f;
[SerializeField] protected float _lift = 0.02f;
/// <summary>
/// Whether this actor's aerodynamic constraints are enabled.
/// </summary>
public bool aerodynamicsEnabled
{
get { return _aerodynamicsEnabled; }
set { if (value != _aerodynamicsEnabled) { _aerodynamicsEnabled = value; SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); } }
}
/// <summary>
/// Aerodynamic drag value.
/// </summary>
public float drag
{
get { return _drag; }
set { _drag = value; SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); }
}
/// <summary>
/// Aerodynamic lift value.
/// </summary>
public float lift
{
get { return _lift; }
set { _lift = value; SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); }
}
public float restLength
{
get { return restLength_; }
}
public ObiPath path
{
get {
var ropeBlueprint = (sourceBlueprint as ObiRopeBlueprintBase);
return ropeBlueprint != null ? ropeBlueprint.path : null;
}
}
public float GetDrag(ObiAerodynamicConstraintsBatch batch, int constraintIndex)
{
return drag;
}
public float GetLift(ObiAerodynamicConstraintsBatch batch, int constraintIndex)
{
return lift;
}
public override void ProvideDeformableEdges(ObiNativeIntList deformableEdges)
{
var ropeBlueprint = sharedBlueprint as ObiRopeBlueprintBase;
if (ropeBlueprint != null && ropeBlueprint.deformableEdges != null)
{
// Send deformable edge indices to the solver:
for (int i = 0; i < ropeBlueprint.deformableEdges.Length; ++i)
deformableEdges.Add(solverIndices[ropeBlueprint.deformableEdges[i]]);
}
}
/// <summary>
/// Calculates and returns current rope length, including stretching/compression.
/// </summary>
public float CalculateLength()
{
float length = 0;
if (isLoaded)
{
// Iterate trough all distance constraints in order:
int elementCount = elements.Count;
for (int i = 0; i < elementCount; ++i)
length += Vector4.Distance(solver.positions[elements[i].particle1], solver.positions[elements[i].particle2]);
}
return length;
}
/// <summary>
/// Recalculates the rope's rest length, that is, its length as specified by the blueprint.
/// </summary>
public void RecalculateRestLength()
{
restLength_ = 0;
// Iterate trough all distance elements and accumulate their rest lengths.
int elementCount = elements.Count;
for (int i = 0; i < elementCount; ++i)
restLength_ += elements[i].restLength;
}
/// <summary>
/// Recalculates all particle rest positions, used when filtering self-collisions.
/// </summary>
public void RecalculateRestPositions()
{
float pos = 0;
int elementCount = elements.Count;
for (int i = 0; i < elementCount; ++i)
{
solver.restPositions[elements[i].particle1] = new Vector4(pos, 0, 0, 1);
pos += elements[i].restLength;
solver.restPositions[elements[i].particle2] = new Vector4(pos, 0, 0, 1);
}
}
/// <summary>
/// Regenerates all rope elements using constraints. It's the opposite of RebuildConstraintsFromElements(). This is automatically called when loading a blueprint, but should also be called when manually
/// altering rope constraints (adding/removing/updating constraints and/or batches).
/// </summary>
public void RebuildElementsFromConstraints()
{
RebuildElementsFromConstraintsInternal();
if (OnElementsGenerated != null)
OnElementsGenerated(this);
}
protected abstract void RebuildElementsFromConstraintsInternal();
/// <summary>
/// Regenerates all rope constraints using rope elements. It's the opposite of RebuildElementsFromConstraints().This should be called anytime the element representation of the rope
/// is changed (adding/removing/updating elements). This is usually the case after tearing the rope or changing its length using a cursor.
/// </summary>
public virtual void RebuildConstraintsFromElements() { }
/// <summary>
/// Returns a rope element that contains a length-normalized coordinate. It will also return the length-normalized coordinate within the element.
/// </summary>
public ObiStructuralElement GetElementAt(float mu, out float elementMu)
{
float edgeMu = elements.Count * Mathf.Clamp(mu, 0, 0.99999f);
int index = (int)edgeMu;
elementMu = edgeMu - index;
if (elements != null && index < elements.Count)
return elements[index];
return null;
}
}
}