修改水
This commit is contained in:
@@ -7,8 +7,7 @@ namespace Obi
|
||||
[AddComponentMenu("Physics/Obi/Obi Bone", 882)]
|
||||
[ExecuteInEditMode]
|
||||
[DisallowMultipleComponent]
|
||||
[DefaultExecutionOrder(100)] // make sure ObiBone's LateUpdate is updated after ObiSolver's.
|
||||
public class ObiBone : ObiActor, IStretchShearConstraintsUser, IBendTwistConstraintsUser, ISkinConstraintsUser, IAerodynamicConstraintsUser
|
||||
public class ObiBone : ObiActor, IStretchShearConstraintsUser, IBendTwistConstraintsUser, ISkinConstraintsUser
|
||||
{
|
||||
[Serializable]
|
||||
public class BonePropertyCurve
|
||||
@@ -32,7 +31,7 @@ namespace Obi
|
||||
[Serializable]
|
||||
public class IgnoredBone
|
||||
{
|
||||
public Transform bone;
|
||||
public Transform bone;
|
||||
public bool ignoreChildren;
|
||||
}
|
||||
|
||||
@@ -40,9 +39,9 @@ namespace Obi
|
||||
|
||||
[SerializeField] protected bool m_SelfCollisions = false;
|
||||
|
||||
[SerializeField] protected BonePropertyCurve _radius = new BonePropertyCurve(0.1f, 1);
|
||||
[SerializeField] protected BonePropertyCurve _mass = new BonePropertyCurve(0.1f, 1);
|
||||
[SerializeField] protected BonePropertyCurve _rotationalMass = new BonePropertyCurve(0.1f, 1);
|
||||
[SerializeField] protected BonePropertyCurve _radius = new BonePropertyCurve(0.1f,1);
|
||||
[SerializeField] protected BonePropertyCurve _mass = new BonePropertyCurve(0.1f,1);
|
||||
[SerializeField] protected BonePropertyCurve _rotationalMass = new BonePropertyCurve(0.1f,1);
|
||||
|
||||
// skin constraints:
|
||||
[SerializeField] protected bool _skinConstraintsEnabled = true;
|
||||
@@ -63,11 +62,6 @@ namespace Obi
|
||||
[SerializeField] protected BonePropertyCurve _plasticYield = new BonePropertyCurve(0, 1);
|
||||
[SerializeField] protected BonePropertyCurve _plasticCreep = new BonePropertyCurve(0, 1);
|
||||
|
||||
// aerodynamics
|
||||
[SerializeField] protected bool _aerodynamicsEnabled = true;
|
||||
[SerializeField] protected BonePropertyCurve _drag = new BonePropertyCurve(0.05f, 1);
|
||||
[SerializeField] protected BonePropertyCurve _lift = new BonePropertyCurve(0.02f, 1);
|
||||
|
||||
[Tooltip("Filter used for collision detection.")]
|
||||
[SerializeField] private int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 1);
|
||||
|
||||
@@ -242,34 +236,7 @@ namespace Obi
|
||||
public BonePropertyCurve plasticCreep
|
||||
{
|
||||
get { return _plasticCreep; }
|
||||
set { _plasticCreep = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
||||
}
|
||||
|
||||
/// <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 BonePropertyCurve drag
|
||||
{
|
||||
get { return _drag; }
|
||||
set { _drag = value; SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aerodynamic lift value.
|
||||
/// </summary>
|
||||
public BonePropertyCurve lift
|
||||
{
|
||||
get { return _lift; }
|
||||
set { _lift = value; SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); }
|
||||
set { _plasticCreep = value; SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
||||
}
|
||||
|
||||
|
||||
@@ -295,7 +262,6 @@ namespace Obi
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
// TODO: guard against having another ObiBone above it in hierarchy.
|
||||
m_BoneBlueprint = ScriptableObject.CreateInstance<ObiBoneBlueprint>();
|
||||
UpdateBlueprint();
|
||||
base.Awake();
|
||||
@@ -331,45 +297,18 @@ namespace Obi
|
||||
}
|
||||
}
|
||||
|
||||
internal override void LoadBlueprint()
|
||||
public override void LoadBlueprint(ObiSolver solver)
|
||||
{
|
||||
base.LoadBlueprint();
|
||||
|
||||
// synchronously read required data from GPU:
|
||||
solver.renderablePositions.Readback(false);
|
||||
solver.renderableOrientations.Readback(false);
|
||||
solver.orientations.Readback(false);
|
||||
solver.angularVelocities.Readback(false);
|
||||
|
||||
base.LoadBlueprint(solver);
|
||||
SetupRuntimeConstraints();
|
||||
ResetToCurrentShape();
|
||||
}
|
||||
|
||||
internal override void UnloadBlueprint()
|
||||
public override void UnloadBlueprint(ObiSolver solver)
|
||||
{
|
||||
ResetParticles();
|
||||
CopyParticleDataToTransforms();
|
||||
base.UnloadBlueprint();
|
||||
}
|
||||
|
||||
public override void RequestReadback()
|
||||
{
|
||||
base.RequestReadback();
|
||||
|
||||
solver.orientations.Readback();
|
||||
solver.angularVelocities.Readback();
|
||||
solver.renderablePositions.Readback();
|
||||
solver.renderableOrientations.Readback();
|
||||
}
|
||||
|
||||
public override void SimulationEnd(float simulatedTime, float substepTime)
|
||||
{
|
||||
base.SimulationEnd(simulatedTime, substepTime);
|
||||
|
||||
solver.orientations.WaitForReadback();
|
||||
solver.angularVelocities.WaitForReadback();
|
||||
solver.renderablePositions.WaitForReadback();
|
||||
solver.renderableOrientations.WaitForReadback();
|
||||
base.UnloadBlueprint(solver);
|
||||
}
|
||||
|
||||
private void SetupRuntimeConstraints()
|
||||
@@ -377,21 +316,10 @@ namespace Obi
|
||||
SetConstraintsDirty(Oni.ConstraintType.Skin);
|
||||
SetConstraintsDirty(Oni.ConstraintType.StretchShear);
|
||||
SetConstraintsDirty(Oni.ConstraintType.BendTwist);
|
||||
SetConstraintsDirty(Oni.ConstraintType.Aerodynamics);
|
||||
SetSelfCollisions(selfCollisions);
|
||||
SetSimplicesDirty();
|
||||
UpdateFilter();
|
||||
}
|
||||
|
||||
public override void ProvideDeformableEdges(ObiNativeIntList deformableEdges)
|
||||
{
|
||||
var boneBprint = sharedBlueprint as ObiBoneBlueprint;
|
||||
if (boneBprint != null && boneBprint.deformableEdges != null)
|
||||
{
|
||||
// Send deformable edge indices to the solver:
|
||||
for (int i = 0; i < boneBprint.deformableEdges.Length; ++i)
|
||||
deformableEdges.Add(solverIndices[boneBprint.deformableEdges[i]]);
|
||||
}
|
||||
UpdateCollisionMaterials();
|
||||
}
|
||||
|
||||
private void FixRoot()
|
||||
@@ -409,10 +337,10 @@ namespace Obi
|
||||
solver.angularVelocities[rootIndex] = Vector4.zero;
|
||||
|
||||
// take particle rest position in actor space (which is always zero), converts to solver space:
|
||||
solver.startPositions[rootIndex] = solver.endPositions[rootIndex] = solver.positions[rootIndex] = actor2Solver.MultiplyPoint3x4(Vector3.zero);
|
||||
solver.renderablePositions[rootIndex] = solver.positions[rootIndex] = actor2Solver.MultiplyPoint3x4(Vector3.zero);
|
||||
|
||||
// take particle rest orientation in actor space, and convert to solver space:
|
||||
solver.startOrientations[rootIndex] = solver.endOrientations[rootIndex] = solver.orientations[rootIndex] = actor2SolverR * boneBlueprint.orientations[0];
|
||||
solver.renderableOrientations[rootIndex] = solver.orientations[rootIndex] = actor2SolverR * boneBlueprint.orientations[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,8 +358,8 @@ namespace Obi
|
||||
{
|
||||
for (int i = 0; i < particleCount; ++i)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(i, out float normalizedCoord);
|
||||
var radii = Vector3.one * (boneOverride != null ? boneOverride.radius.Evaluate(normalizedCoord) : radius.Evaluate(normalizedCoord));
|
||||
var normalizedCoord = boneBlueprint.normalizedLengths[i];
|
||||
var radii = Vector3.one * radius.Evaluate(normalizedCoord);
|
||||
boneBlueprint.principalRadii[i] = radii;
|
||||
|
||||
if (isLoaded)
|
||||
@@ -443,9 +371,9 @@ namespace Obi
|
||||
{
|
||||
for (int i = 0; i < particleCount; ++i)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(i, out float normalizedCoord);
|
||||
var invMass = ObiUtils.MassToInvMass(boneOverride != null ? boneOverride .mass.Evaluate(normalizedCoord) : mass.Evaluate(normalizedCoord));
|
||||
var invRotMass = ObiUtils.MassToInvMass(boneOverride != null ? boneOverride.rotationalMass.Evaluate(normalizedCoord) : rotationalMass.Evaluate(normalizedCoord));
|
||||
var normalizedCoord = boneBlueprint.normalizedLengths[i];
|
||||
var invMass = ObiUtils.MassToInvMass(mass.Evaluate(normalizedCoord));
|
||||
var invRotMass = ObiUtils.MassToInvMass(rotationalMass.Evaluate(normalizedCoord));
|
||||
|
||||
boneBlueprint.invMasses[i] = invMass;
|
||||
boneBlueprint.invRotationalMasses[i] = invRotMass;
|
||||
@@ -460,24 +388,20 @@ namespace Obi
|
||||
|
||||
public Vector3 GetSkinRadiiBackstop(ObiSkinConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(batch.particleIndices[constraintIndex], out float normalizedCoord);
|
||||
return new Vector3(boneOverride != null ? boneOverride.skinRadius.Evaluate(normalizedCoord) : skinRadius.Evaluate(normalizedCoord), 0, 0);
|
||||
float normalizedCoord = boneBlueprint.normalizedLengths[batch.particleIndices[constraintIndex]];
|
||||
return new Vector3(skinRadius.Evaluate(normalizedCoord),0,0);
|
||||
}
|
||||
|
||||
public float GetSkinCompliance(ObiSkinConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(batch.particleIndices[constraintIndex], out float normalizedCoord);
|
||||
return boneOverride != null ? boneOverride.skinCompliance.Evaluate(normalizedCoord) : skinCompliance.Evaluate(normalizedCoord);
|
||||
float normalizedCoord = boneBlueprint.normalizedLengths[batch.particleIndices[constraintIndex]];
|
||||
return skinCompliance.Evaluate(normalizedCoord);
|
||||
}
|
||||
|
||||
|
||||
public Vector3 GetBendTwistCompliance(ObiBendTwistConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(batch.particleIndices[constraintIndex * 2], out float normalizedCoord);
|
||||
|
||||
if (boneOverride != null)
|
||||
return new Vector3(boneOverride.bend1Compliance.Evaluate(normalizedCoord),
|
||||
boneOverride.bend2Compliance.Evaluate(normalizedCoord),
|
||||
boneOverride.torsionCompliance.Evaluate(normalizedCoord));
|
||||
float normalizedCoord = boneBlueprint.normalizedLengths[batch.particleIndices[constraintIndex * 2]];
|
||||
return new Vector3(bend1Compliance.Evaluate(normalizedCoord),
|
||||
bend2Compliance.Evaluate(normalizedCoord),
|
||||
torsionCompliance.Evaluate(normalizedCoord));
|
||||
@@ -485,51 +409,22 @@ namespace Obi
|
||||
|
||||
public Vector2 GetBendTwistPlasticity(ObiBendTwistConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(batch.particleIndices[constraintIndex * 2], out float normalizedCoord);
|
||||
|
||||
if (boneOverride != null)
|
||||
return new Vector2(boneOverride.plasticYield.Evaluate(normalizedCoord),
|
||||
boneOverride.plasticCreep.Evaluate(normalizedCoord));
|
||||
float normalizedCoord = boneBlueprint.normalizedLengths[batch.particleIndices[constraintIndex * 2]];
|
||||
return new Vector2(plasticYield.Evaluate(normalizedCoord),
|
||||
plasticCreep.Evaluate(normalizedCoord));
|
||||
|
||||
}
|
||||
|
||||
public Vector3 GetStretchShearCompliance(ObiStretchShearConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(batch.particleIndices[constraintIndex * 2], out float normalizedCoord);
|
||||
|
||||
if (boneOverride != null)
|
||||
return new Vector3(boneOverride.shear1Compliance.Evaluate(normalizedCoord),
|
||||
boneOverride.shear2Compliance.Evaluate(normalizedCoord),
|
||||
boneOverride.stretchCompliance.Evaluate(normalizedCoord));
|
||||
float normalizedCoord = boneBlueprint.normalizedLengths[batch.particleIndices[constraintIndex * 2]];
|
||||
return new Vector3(shear1Compliance.Evaluate(normalizedCoord),
|
||||
shear2Compliance.Evaluate(normalizedCoord),
|
||||
stretchCompliance.Evaluate(normalizedCoord));
|
||||
}
|
||||
|
||||
public float GetDrag(ObiAerodynamicConstraintsBatch batch, int constraintIndex)
|
||||
public override void BeginStep(float stepTime)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(batch.particleIndices[constraintIndex], out float normalizedCoord);
|
||||
return boneOverride != null ? boneOverride.drag.Evaluate(normalizedCoord) : drag.Evaluate(normalizedCoord);
|
||||
}
|
||||
|
||||
public float GetLift(ObiAerodynamicConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
var boneOverride = boneBlueprint.GetOverride(batch.particleIndices[constraintIndex], out float normalizedCoord);
|
||||
return boneOverride != null ? boneOverride.lift.Evaluate(normalizedCoord) : lift.Evaluate(normalizedCoord);
|
||||
}
|
||||
|
||||
public void FixedUpdate()
|
||||
{
|
||||
// This resets all bones not affected by animation,
|
||||
// needs to happen once per frame at the very start before Animators are updated.
|
||||
ResetReferenceOrientations();
|
||||
}
|
||||
|
||||
public override void SimulationStart(float timeToSimulate, float substepTime)
|
||||
{
|
||||
base.SimulationStart(timeToSimulate, substepTime);
|
||||
base.BeginStep(stepTime);
|
||||
|
||||
if (fixRoot)
|
||||
FixRoot();
|
||||
@@ -537,10 +432,18 @@ namespace Obi
|
||||
UpdateRestShape();
|
||||
}
|
||||
|
||||
public void LateUpdate()
|
||||
public override void PrepareFrame()
|
||||
{
|
||||
ResetReferenceOrientations();
|
||||
base.PrepareFrame();
|
||||
}
|
||||
|
||||
public override void Interpolate()
|
||||
{
|
||||
if (Application.isPlaying && isActiveAndEnabled)
|
||||
CopyParticleDataToTransforms();
|
||||
|
||||
base.Interpolate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -560,49 +463,11 @@ namespace Obi
|
||||
solver.velocities[solverIndex] = Vector4.zero;
|
||||
solver.angularVelocities[solverIndex] = Vector4.zero;
|
||||
|
||||
solver.startPositions[solverIndex] = solver.endPositions[solverIndex] = solver.positions[solverIndex] = world2Solver.MultiplyPoint3x4(trfm.position);
|
||||
solver.renderablePositions[solverIndex] = solver.positions[solverIndex] = world2Solver.MultiplyPoint3x4(trfm.position);
|
||||
|
||||
var boneDeltaAWS = trfm.rotation * Quaternion.Inverse(boneBlueprint.restOrientations[i]);
|
||||
solver.startOrientations[solverIndex] = solver.endOrientations[solverIndex] = solver.orientations[solverIndex] = world2Solver.rotation * boneDeltaAWS * boneBlueprint.root2WorldR * boneBlueprint.orientations[i];
|
||||
solver.renderableOrientations[solverIndex] = solver.orientations[solverIndex] = world2Solver.rotation * boneDeltaAWS * boneBlueprint.root2WorldR * boneBlueprint.orientations[i];
|
||||
}
|
||||
|
||||
// Update constraint data in the blueprint, since StartSimulation won't be called until next frame.
|
||||
var bc = GetConstraintsByType(Oni.ConstraintType.BendTwist) as ObiConstraints<ObiBendTwistConstraintsBatch>;
|
||||
|
||||
if (bc != null)
|
||||
for (int j = 0; j < bc.batchCount; ++j)
|
||||
{
|
||||
var batch = bc.GetBatch(j) as ObiBendTwistConstraintsBatch;
|
||||
|
||||
for (int i = 0; i < batch.activeConstraintCount; i++)
|
||||
{
|
||||
int indexA = batch.particleIndices[i * 2];
|
||||
int indexB = batch.particleIndices[i * 2 + 1];
|
||||
|
||||
// calculate bone rotation delta in world space:
|
||||
var boneDeltaAWS = boneBlueprint.transforms[indexA].rotation * Quaternion.Inverse(boneBlueprint.restOrientations[indexA]);
|
||||
var boneDeltaBWS = boneBlueprint.transforms[indexB].rotation * Quaternion.Inverse(boneBlueprint.restOrientations[indexB]);
|
||||
|
||||
// apply delta to rest particle orientation:
|
||||
var orientationA = boneDeltaAWS * boneBlueprint.root2WorldR * boneBlueprint.orientations[indexA];
|
||||
var orientationB = boneDeltaBWS * boneBlueprint.root2WorldR * boneBlueprint.orientations[indexB];
|
||||
|
||||
batch.restDarbouxVectors[i] = ObiUtils.RestDarboux(orientationA, orientationB);
|
||||
}
|
||||
}
|
||||
|
||||
var sc = GetConstraintsByType(Oni.ConstraintType.Skin) as ObiConstraints<ObiSkinConstraintsBatch>;
|
||||
|
||||
if (sc != null)
|
||||
for (int j = 0; j < sc.batchCount; ++j)
|
||||
{
|
||||
var batch = sc.GetBatch(j) as ObiSkinConstraintsBatch;
|
||||
for (int i = 0; i < batch.activeConstraintCount; i++)
|
||||
{
|
||||
int index = batch.particleIndices[i];
|
||||
batch.skinPoints[i] = solver.transform.worldToLocalMatrix.MultiplyPoint3x4(boneBlueprint.transforms[index].position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetReferenceOrientations()
|
||||
@@ -619,20 +484,14 @@ namespace Obi
|
||||
var sbc = solver.GetConstraintsByType(Oni.ConstraintType.BendTwist) as ObiConstraints<ObiBendTwistConstraintsBatch>;
|
||||
|
||||
if (bendTwistConstraintsEnabled && bc != null && sbc != null)
|
||||
{
|
||||
// iterate up to the amount of entries in solverBatchOffsets, insteaf of bc.batchCount. This ensures
|
||||
// the batches we access have been added to the solver, as solver.UpdateConstraints() could have not been called yet on a newly added actor.
|
||||
for (int j = 0; j < solverBatchOffsets[(int)Oni.ConstraintType.BendTwist].Count; ++j)
|
||||
for (int j = 0; j < bc.GetBatchCount(); ++j)
|
||||
{
|
||||
var batch = bc.GetBatch(j) as ObiBendTwistConstraintsBatch;
|
||||
var solverBatch = sbc.batches[j] as ObiBendTwistConstraintsBatch;
|
||||
int offset = solverBatchOffsets[(int)Oni.ConstraintType.BendTwist][j];
|
||||
int offset = solverBatchOffsets[(int)solverBatch.constraintType][j];
|
||||
|
||||
if (solverBatch.restDarbouxVectors.isCreated)
|
||||
{
|
||||
if (solverBatch.restDarbouxVectors.computeBuffer == null)
|
||||
solverBatch.restDarbouxVectors.SafeAsComputeBuffer<Vector4>();
|
||||
|
||||
for (int i = 0; i < batch.activeConstraintCount; i++)
|
||||
{
|
||||
int indexA = batch.particleIndices[i * 2];
|
||||
@@ -648,45 +507,34 @@ namespace Obi
|
||||
|
||||
solverBatch.restDarbouxVectors[offset + i] = ObiUtils.RestDarboux(orientationA, orientationB);
|
||||
}
|
||||
|
||||
solverBatch.restDarbouxVectors.Upload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sc = GetConstraintsByType(Oni.ConstraintType.Skin) as ObiConstraints<ObiSkinConstraintsBatch>;
|
||||
var ssc = solver.GetConstraintsByType(Oni.ConstraintType.Skin) as ObiConstraints<ObiSkinConstraintsBatch>;
|
||||
|
||||
if (skinConstraintsEnabled && sc != null && ssc != null)
|
||||
{
|
||||
// iterate up to the amount of entries in solverBatchOffsets, insteaf of sc.batchCount. This ensures
|
||||
// the batches we access have been added to the solver, as solver.UpdateConstraints() could have not been called yet on a newly added actor.
|
||||
for (int j = 0; j < solverBatchOffsets[(int)Oni.ConstraintType.Skin].Count; ++j)
|
||||
for (int j = 0; j < sc.GetBatchCount(); ++j)
|
||||
{
|
||||
var batch = sc.GetBatch(j) as ObiSkinConstraintsBatch;
|
||||
var solverBatch = ssc.batches[j] as ObiSkinConstraintsBatch;
|
||||
int offset = solverBatchOffsets[(int)Oni.ConstraintType.Skin][j];
|
||||
int offset = solverBatchOffsets[(int)solverBatch.constraintType][j];
|
||||
|
||||
if (solverBatch.skinPoints.isCreated)
|
||||
{
|
||||
if (solverBatch.skinPoints.computeBuffer == null)
|
||||
solverBatch.skinPoints.SafeAsComputeBuffer<Vector4>();
|
||||
|
||||
for (int i = 0; i < batch.activeConstraintCount; i++)
|
||||
{
|
||||
int index = batch.particleIndices[i];
|
||||
solverBatch.skinPoints[offset + i] = solver.transform.worldToLocalMatrix.MultiplyPoint3x4(boneBlueprint.transforms[index].position);
|
||||
}
|
||||
|
||||
solverBatch.skinPoints.Upload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CopyParticleDataToTransforms()
|
||||
{
|
||||
if (isLoaded && boneBlueprint != null)
|
||||
|
||||
if (boneBlueprint != null)
|
||||
{
|
||||
// copy current particle transforms to bones:
|
||||
for (int i = 1; i < particleCount; ++i)
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[AddComponentMenu("Physics/Obi/Obi Bone Override", 882)]
|
||||
[ExecuteInEditMode]
|
||||
[DisallowMultipleComponent]
|
||||
public class ObiBoneOverride : MonoBehaviour
|
||||
{
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _radius = new ObiBone.BonePropertyCurve(0.1f, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _mass = new ObiBone.BonePropertyCurve(0.1f, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _rotationalMass = new ObiBone.BonePropertyCurve(0.1f, 1);
|
||||
|
||||
// skin constraints:
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _skinCompliance = new ObiBone.BonePropertyCurve(0.01f, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _skinRadius = new ObiBone.BonePropertyCurve(0.1f, 1);
|
||||
|
||||
// distance constraints:
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _stretchCompliance = new ObiBone.BonePropertyCurve(0, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _shear1Compliance = new ObiBone.BonePropertyCurve(0, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _shear2Compliance = new ObiBone.BonePropertyCurve(0, 1);
|
||||
|
||||
// bend constraints:
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _torsionCompliance = new ObiBone.BonePropertyCurve(0, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _bend1Compliance = new ObiBone.BonePropertyCurve(0, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _bend2Compliance = new ObiBone.BonePropertyCurve(0, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _plasticYield = new ObiBone.BonePropertyCurve(0, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _plasticCreep = new ObiBone.BonePropertyCurve(0, 1);
|
||||
|
||||
// aerodynamics
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _drag = new ObiBone.BonePropertyCurve(0.05f, 1);
|
||||
[SerializeField] protected ObiBone.BonePropertyCurve _lift = new ObiBone.BonePropertyCurve(0.02f, 1);
|
||||
|
||||
/// <summary>
|
||||
/// Particle radius distribution over this bone hierarchy length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve radius
|
||||
{
|
||||
get { return _radius; }
|
||||
set { _radius = value; bone.UpdateRadius(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mass distribution over this bone hierarchy length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve mass
|
||||
{
|
||||
get { return _mass; }
|
||||
set { _mass = value; bone.UpdateMasses(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotational mass distribution over this bone hierarchy length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve rotationalMass
|
||||
{
|
||||
get { return _rotationalMass; }
|
||||
set { _rotationalMass = value; bone.UpdateMasses(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compliance of this actor's skin constraints.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve skinCompliance
|
||||
{
|
||||
get { return _skinCompliance; }
|
||||
set { _skinCompliance = value; bone.SetConstraintsDirty(Oni.ConstraintType.Skin); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compliance of this actor's skin radius
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve skinRadius
|
||||
{
|
||||
get { return _skinRadius; }
|
||||
set { _skinRadius = value; bone.SetConstraintsDirty(Oni.ConstraintType.Skin); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compliance of this actor's stretch/shear constraints, along their length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve stretchCompliance
|
||||
{
|
||||
get { return _stretchCompliance; }
|
||||
set { _stretchCompliance = value; bone.SetConstraintsDirty(Oni.ConstraintType.StretchShear); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shearing compliance of this actor's stretch/shear constraints, along the first axis orthogonal to their length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve shear1Compliance
|
||||
{
|
||||
get { return _shear1Compliance; }
|
||||
set { _shear1Compliance = value; bone.SetConstraintsDirty(Oni.ConstraintType.StretchShear); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shearing compliance of this actor's stretch/shear constraints, along the second axis orthogonal to their length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve shear2Compliance
|
||||
{
|
||||
get { return _shear2Compliance; }
|
||||
set { _shear2Compliance = value; bone.SetConstraintsDirty(Oni.ConstraintType.StretchShear); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Torsional compliance of this actor's bend/twist constraints along their length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve torsionCompliance
|
||||
{
|
||||
get { return _torsionCompliance; }
|
||||
set { _torsionCompliance = value; bone.SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bending compliance of this actor's bend/twist constraints along the first axis orthogonal to their length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve bend1Compliance
|
||||
{
|
||||
get { return _bend1Compliance; }
|
||||
set { _bend1Compliance = value; bone.SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bending compliance of this actor's bend/twist constraints along the second axis orthogonal to their length.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve bend2Compliance
|
||||
{
|
||||
get { return _bend2Compliance; }
|
||||
set { _bend2Compliance = value; bone.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 ObiBone.BonePropertyCurve plasticYield
|
||||
{
|
||||
get { return _plasticYield; }
|
||||
set { _plasticYield = value; bone.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 ObiBone.BonePropertyCurve plasticCreep
|
||||
{
|
||||
get { return _plasticCreep; }
|
||||
set { _plasticCreep = value; bone.SetConstraintsDirty(Oni.ConstraintType.BendTwist); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aerodynamic drag value.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve drag
|
||||
{
|
||||
get { return _drag; }
|
||||
set { _drag = value; bone.SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aerodynamic lift value.
|
||||
/// </summary>
|
||||
public ObiBone.BonePropertyCurve lift
|
||||
{
|
||||
get { return _lift; }
|
||||
set { _lift = value; bone.SetConstraintsDirty(Oni.ConstraintType.Aerodynamics); }
|
||||
}
|
||||
|
||||
private ObiBone bone;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
bone = GetComponentInParent<ObiBone>();
|
||||
}
|
||||
|
||||
protected void OnValidate()
|
||||
{
|
||||
if (bone != null)
|
||||
{
|
||||
bone.UpdateRadius();
|
||||
bone.UpdateMasses();
|
||||
bone.SetConstraintsDirty(Oni.ConstraintType.Skin);
|
||||
bone.SetConstraintsDirty(Oni.ConstraintType.StretchShear);
|
||||
bone.SetConstraintsDirty(Oni.ConstraintType.BendTwist);
|
||||
bone.SetConstraintsDirty(Oni.ConstraintType.Aerodynamics);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eed7ac246d14742e5a77c218f4e491ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 0a18e0376cc184a9b96ebb3bf0175cc2, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -183,35 +183,22 @@ namespace Obi
|
||||
SetupRuntimeConstraints();
|
||||
}
|
||||
|
||||
internal override void LoadBlueprint()
|
||||
public override void LoadBlueprint(ObiSolver solver)
|
||||
{
|
||||
base.LoadBlueprint();
|
||||
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.BendTwist);
|
||||
SetConstraintsDirty(Oni.ConstraintType.Chain);
|
||||
SetConstraintsDirty(Oni.ConstraintType.Aerodynamics);
|
||||
SetSelfCollisions(selfCollisions);
|
||||
SetMassScale(m_MassScale);
|
||||
RecalculateRestLength();
|
||||
SetSimplicesDirty();
|
||||
UpdateCollisionMaterials();
|
||||
}
|
||||
|
||||
public Vector3 GetBendTwistCompliance(ObiBendTwistConstraintsBatch batch, int constraintIndex)
|
||||
@@ -232,7 +219,7 @@ namespace Obi
|
||||
protected override void RebuildElementsFromConstraintsInternal()
|
||||
{
|
||||
var dc = GetConstraintsByType(Oni.ConstraintType.StretchShear) as ObiConstraints<ObiStretchShearConstraintsBatch>;
|
||||
if (dc == null || dc.batchCount < 2)
|
||||
if (dc == null || dc.GetBatchCount() < 2)
|
||||
return;
|
||||
|
||||
int constraintCount = dc.batches[0].activeConstraintCount + dc.batches[1].activeConstraintCount;
|
||||
|
||||
@@ -178,20 +178,20 @@ namespace Obi
|
||||
SetupRuntimeConstraints();
|
||||
}
|
||||
|
||||
internal override void LoadBlueprint()
|
||||
public override void LoadBlueprint(ObiSolver solver)
|
||||
{
|
||||
// create a copy of the blueprint for this cloth:
|
||||
if (Application.isPlaying)
|
||||
m_RopeBlueprintInstance = this.blueprint as ObiRopeBlueprint;
|
||||
|
||||
base.LoadBlueprint();
|
||||
base.LoadBlueprint(solver);
|
||||
RebuildElementsFromConstraints();
|
||||
SetupRuntimeConstraints();
|
||||
}
|
||||
|
||||
internal override void UnloadBlueprint()
|
||||
public override void UnloadBlueprint(ObiSolver solver)
|
||||
{
|
||||
base.UnloadBlueprint();
|
||||
base.UnloadBlueprint(solver);
|
||||
|
||||
// delete the blueprint instance:
|
||||
if (m_RopeBlueprintInstance != null)
|
||||
@@ -202,25 +202,26 @@ namespace Obi
|
||||
{
|
||||
SetConstraintsDirty(Oni.ConstraintType.Distance);
|
||||
SetConstraintsDirty(Oni.ConstraintType.Bending);
|
||||
SetConstraintsDirty(Oni.ConstraintType.Aerodynamics);
|
||||
SetSelfCollisions(selfCollisions);
|
||||
SetMassScale(m_MassScale);
|
||||
RecalculateRestLength();
|
||||
SetSimplicesDirty();
|
||||
UpdateCollisionMaterials();
|
||||
}
|
||||
|
||||
// Tearing must be done at the end of each step instead of substep, to give a chance to solver constraints to be rebuilt.
|
||||
public override void SimulationStart(float timeToSimulate, float substepTime)
|
||||
public override void Substep(float substepTime)
|
||||
{
|
||||
base.SimulationStart(timeToSimulate, substepTime);
|
||||
base.Substep(substepTime);
|
||||
|
||||
if (isActiveAndEnabled && tearingEnabled)
|
||||
if (isActiveAndEnabled)
|
||||
ApplyTearing(substepTime);
|
||||
}
|
||||
|
||||
protected void ApplyTearing(float substepTime)
|
||||
{
|
||||
|
||||
if (!tearingEnabled)
|
||||
return;
|
||||
|
||||
float sqrTime = substepTime * substepTime;
|
||||
|
||||
tornElements.Clear();
|
||||
@@ -229,28 +230,24 @@ namespace Obi
|
||||
var sc = this.solver.GetConstraintsByType(Oni.ConstraintType.Distance) as ObiConstraints<ObiDistanceConstraintsBatch>;
|
||||
|
||||
if (dc != null && sc != null)
|
||||
for (int j = 0; j < dc.GetBatchCount(); ++j)
|
||||
{
|
||||
// iterate up to the amount of entries in solverBatchOffsets, insteaf of dc.batchCount. This ensures
|
||||
// the batches we access have been added to the solver, as solver.UpdateConstraints() could have not been called yet on a newly added actor.
|
||||
for (int j = 0; j < solverBatchOffsets[(int)Oni.ConstraintType.Distance].Count; ++j)
|
||||
var batch = dc.GetBatch(j) as ObiDistanceConstraintsBatch;
|
||||
var solverBatch = sc.batches[j] as ObiDistanceConstraintsBatch;
|
||||
|
||||
for (int i = 0; i < batch.activeConstraintCount; i++)
|
||||
{
|
||||
var batch = dc.GetBatch(j) as ObiDistanceConstraintsBatch;
|
||||
var solverBatch = sc.batches[j] as ObiDistanceConstraintsBatch;
|
||||
int elementIndex = j + 2 * i;
|
||||
|
||||
for (int i = 0; i < batch.activeConstraintCount; i++)
|
||||
// divide lambda by squared delta time to get force in newtons:
|
||||
int offset = solverBatchOffsets[(int)Oni.ConstraintType.Distance][j];
|
||||
float force = solverBatch.lambdas[offset + i] / sqrTime;
|
||||
|
||||
elements[elementIndex].constraintForce = force;
|
||||
|
||||
if (-force > tearResistanceMultiplier)
|
||||
{
|
||||
int elementIndex = j + 2 * i;
|
||||
|
||||
// divide lambda by squared delta time to get force in newtons:
|
||||
int offset = solverBatchOffsets[(int)Oni.ConstraintType.Distance][j];
|
||||
float force = solverBatch.lambdas[offset + i] / sqrTime;
|
||||
|
||||
elements[elementIndex].constraintForce = force;
|
||||
|
||||
if (-force > tearResistanceMultiplier)
|
||||
{
|
||||
tornElements.Add(elements[elementIndex]);
|
||||
}
|
||||
tornElements.Add(elements[elementIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,8 +282,7 @@ namespace Obi
|
||||
m_Solver.invMasses[splitIndex] *= 2;
|
||||
|
||||
CopyParticle(solver.particleToActor[splitIndex].indexInActor, activeParticleCount);
|
||||
ActivateParticle();
|
||||
SetRenderingDirty(Oni.RenderingSystemType.AllRopes);
|
||||
ActivateParticle(activeParticleCount);
|
||||
|
||||
return solverIndices[activeParticleCount - 1];
|
||||
}
|
||||
@@ -313,7 +309,8 @@ namespace Obi
|
||||
|
||||
element.particle1 = SplitParticle(element.particle1);
|
||||
|
||||
OnRopeTorn?.Invoke(this, new ObiRopeTornEventArgs(element, element.particle1));
|
||||
if (OnRopeTorn != null)
|
||||
OnRopeTorn(this, new ObiRopeTornEventArgs(element, element.particle1));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -321,7 +318,7 @@ namespace Obi
|
||||
protected override void RebuildElementsFromConstraintsInternal()
|
||||
{
|
||||
var dc = GetConstraintsByType(Oni.ConstraintType.Distance) as ObiConstraints<ObiDistanceConstraintsBatch>;
|
||||
if (dc == null || dc.batchCount < 2)
|
||||
if (dc == null || dc.GetBatchCount() < 2)
|
||||
return;
|
||||
|
||||
int constraintCount = dc.batches[0].activeConstraintCount + dc.batches[1].activeConstraintCount;
|
||||
@@ -359,26 +356,13 @@ namespace Obi
|
||||
// regenerate constraints from elements:
|
||||
var dc = GetConstraintsByType(Oni.ConstraintType.Distance) as ObiConstraints<ObiDistanceConstraintsBatch>;
|
||||
var bc = GetConstraintsByType(Oni.ConstraintType.Bending) as ObiConstraints<ObiBendConstraintsBatch>;
|
||||
var ac = GetConstraintsByType(Oni.ConstraintType.Aerodynamics) as ObiConstraints<ObiAerodynamicConstraintsBatch>;
|
||||
|
||||
dc.DeactivateAllConstraints();
|
||||
bc.DeactivateAllConstraints();
|
||||
ac.DeactivateAllConstraints();
|
||||
|
||||
for (int i = 0; i < activeParticleCount; ++i)
|
||||
{
|
||||
// aerodynamic constraints:
|
||||
var ab = ac.batches[0] as ObiAerodynamicConstraintsBatch;
|
||||
int constraint = ab.activeConstraintCount;
|
||||
ab.particleIndices[constraint] = i;
|
||||
ab.aerodynamicCoeffs[constraint * 3] = 2 * solver.principalRadii[solverIndices[i]].x;
|
||||
ab.ActivateConstraint(constraint);
|
||||
}
|
||||
|
||||
int elementsCount = elements.Count - (ropeBlueprint.path.Closed ? 1 : 0);
|
||||
for (int i = 0; i < elementsCount; ++i)
|
||||
{
|
||||
// distance constraints
|
||||
var db = dc.batches[i % 2] as ObiDistanceConstraintsBatch;
|
||||
int constraint = db.activeConstraintCount;
|
||||
|
||||
@@ -388,7 +372,6 @@ namespace Obi
|
||||
db.stiffnesses[constraint] = new Vector2(_stretchCompliance, _maxCompression * db.restLengths[constraint]);
|
||||
db.ActivateConstraint(constraint);
|
||||
|
||||
// bend constraints
|
||||
if (i < elementsCount - 1)
|
||||
{
|
||||
var bb = bc.batches[i % 3] as ObiBendConstraintsBatch;
|
||||
@@ -401,7 +384,7 @@ namespace Obi
|
||||
int indexA = elements[i].particle1;
|
||||
int indexB = elements[i + 1].particle2;
|
||||
int indexC = elements[i].particle2;
|
||||
float restBend = 0;//ObiUtils.RestBendingConstraint(solver.restPositions[indexA], solver.restPositions[indexB], solver.restPositions[indexC]);
|
||||
float restBend = ObiUtils.RestBendingConstraint(solver.restPositions[indexA], solver.restPositions[indexB], solver.restPositions[indexC]);
|
||||
|
||||
bb.particleIndices[constraint * 3] = solver.particleToActor[indexA].indexInActor;
|
||||
bb.particleIndices[constraint * 3 + 1] = solver.particleToActor[indexB].indexInActor;
|
||||
@@ -447,21 +430,16 @@ namespace Obi
|
||||
loopClosingBatch.ActivateConstraint(0);
|
||||
}
|
||||
|
||||
// edge simplices and deformable edges
|
||||
var rb = sharedBlueprint as ObiRopeBlueprint;
|
||||
rb.edges = new int[elements.Count * 2];
|
||||
rb.deformableEdges = new int[elements.Count * 2];
|
||||
// edge simplices:
|
||||
sharedBlueprint.edges = new int[elements.Count*2];
|
||||
for (int i = 0; i < elements.Count; ++i)
|
||||
{
|
||||
rb.deformableEdges[i * 2] = rb.edges[i * 2] = solver.particleToActor[elements[i].particle1].indexInActor;
|
||||
rb.deformableEdges[i * 2 + 1] = rb.edges[i * 2 + 1] = solver.particleToActor[elements[i].particle2].indexInActor;
|
||||
sharedBlueprint.edges[i * 2] = solver.particleToActor[elements[i].particle1].indexInActor;
|
||||
sharedBlueprint.edges[i * 2 + 1] = solver.particleToActor[elements[i].particle2].indexInActor;
|
||||
}
|
||||
|
||||
SetConstraintsDirty(Oni.ConstraintType.Distance);
|
||||
SetConstraintsDirty(Oni.ConstraintType.Bending);
|
||||
SetConstraintsDirty(Oni.ConstraintType.Aerodynamics);
|
||||
|
||||
solver.dirtyDeformableEdges = true;
|
||||
SetSimplicesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiRopeBase : ObiActor, IAerodynamicConstraintsUser
|
||||
public abstract class ObiRopeBase : ObiActor
|
||||
{
|
||||
|
||||
[SerializeField] protected bool m_SelfCollisions = false;
|
||||
@@ -12,44 +12,11 @@ namespace Obi
|
||||
[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 {
|
||||
@@ -58,37 +25,6 @@ namespace Obi
|
||||
}
|
||||
}
|
||||
|
||||
public float GetDrag(ObiAerodynamicConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
return drag;
|
||||
}
|
||||
|
||||
public float GetLift(ObiAerodynamicConstraintsBatch batch, int constraintIndex)
|
||||
{
|
||||
return lift;
|
||||
}
|
||||
|
||||
public override void ProvideDeformableEdges(ObiNativeIntList deformableEdges)
|
||||
{
|
||||
deformableEdgesOffset = deformableEdges.count / 2;
|
||||
|
||||
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]]);
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetDeformableEdgeCount()
|
||||
{
|
||||
var ropeBlueprint = sharedBlueprint as ObiRopeBlueprintBase;
|
||||
if (ropeBlueprint != null && ropeBlueprint.deformableEdges != null)
|
||||
return ropeBlueprint.deformableEdges.Length / 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates and returns current rope length, including stretching/compression.
|
||||
/// </summary>
|
||||
@@ -169,25 +105,5 @@ namespace Obi
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns index of the edge that contains a length-normalized coordinate. It will also return the length-normalized coordinate within the edge.
|
||||
/// </summary>
|
||||
public int GetEdgeAt(float mu, out float elementMu)
|
||||
{
|
||||
elementMu = -1;
|
||||
var ropeBlueprint = sharedBlueprint as ObiRopeBlueprintBase;
|
||||
if (ropeBlueprint != null && ropeBlueprint.deformableEdges != null)
|
||||
{
|
||||
float edgeMu = ropeBlueprint.deformableEdges.Length/2 * Mathf.Clamp(mu, 0, 0.99999f);
|
||||
|
||||
int index = (int)edgeMu;
|
||||
elementMu = edgeMu - index;
|
||||
|
||||
if (index < ropeBlueprint.deformableEdges.Length/2)
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ namespace Obi
|
||||
|
||||
ObiStructuralElement m_CursorElement = null;
|
||||
private int m_SourceIndex = -1;
|
||||
private float lengthChange = 0;
|
||||
|
||||
public float cursorMu
|
||||
{
|
||||
@@ -67,7 +66,6 @@ namespace Obi
|
||||
rope = GetComponent<ObiRope>();
|
||||
|
||||
rope.OnElementsGenerated += Actor_OnElementsGenerated;
|
||||
rope.OnSimulationStart += Rope_OnSimulate;
|
||||
if (rope.elements != null && rope.elements.Count > 0)
|
||||
Actor_OnElementsGenerated(rope);
|
||||
}
|
||||
@@ -75,7 +73,6 @@ namespace Obi
|
||||
private void OnDisable()
|
||||
{
|
||||
rope.OnElementsGenerated -= Actor_OnElementsGenerated;
|
||||
rope.OnSimulationStart -= Rope_OnSimulate;
|
||||
}
|
||||
|
||||
private void Actor_OnElementsGenerated(ObiActor actor)
|
||||
@@ -84,13 +81,64 @@ namespace Obi
|
||||
UpdateSource();
|
||||
}
|
||||
|
||||
private void Rope_OnSimulate(ObiActor actor, float simulatedTime, float substepTime)
|
||||
public void UpdateCursor()
|
||||
{
|
||||
if (!rope.isLoaded || Mathf.Abs(lengthChange) < ObiUtils.epsilon)
|
||||
rope = GetComponent<ObiRope>();
|
||||
m_CursorElement = null;
|
||||
if (rope.isLoaded)
|
||||
{
|
||||
float elmMu;
|
||||
m_CursorElement = rope.GetElementAt(cursorMu, out elmMu);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSource()
|
||||
{
|
||||
rope = GetComponent<ObiRope>();
|
||||
m_SourceIndex = -1;
|
||||
if (rope.isLoaded)
|
||||
{
|
||||
float elmMu;
|
||||
var elm = rope.GetElementAt(sourceMu, out elmMu);
|
||||
if (elm != null && rope.solver != null)
|
||||
{
|
||||
m_SourceIndex = elmMu < 0.5f ? elm.particle1 : elm.particle2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int AddParticleAt(int index)
|
||||
{
|
||||
// Copy data from the particle where we will insert new particles, to the particles we will insert:
|
||||
int targetIndex = rope.activeParticleCount;
|
||||
rope.CopyParticle(rope.solver.particleToActor[m_SourceIndex].indexInActor, targetIndex);
|
||||
|
||||
// Move the new particle to the one at the place where we will insert it:
|
||||
rope.TeleportParticle(targetIndex, rope.solver.positions[rope.solverIndices[index]]);
|
||||
|
||||
// Activate the particle:
|
||||
rope.ActivateParticle(targetIndex);
|
||||
return rope.solverIndices[targetIndex];
|
||||
}
|
||||
|
||||
private void RemoveParticleAt(int index)
|
||||
{
|
||||
rope.DeactivateParticle(index);
|
||||
}
|
||||
|
||||
public void ChangeLength(float newLength)
|
||||
{
|
||||
if (!rope.isLoaded)
|
||||
return;
|
||||
|
||||
var solver = rope.solver;
|
||||
|
||||
// clamp new length to sane limits:
|
||||
newLength = Mathf.Clamp(newLength, 0, (rope.sourceBlueprint.particleCount - 1) * rope.ropeBlueprint.interParticleDistance);
|
||||
|
||||
// calculate the change in rope length:
|
||||
float lengthChange = newLength - rope.restLength;
|
||||
|
||||
// remove:
|
||||
if (lengthChange < 0)
|
||||
{
|
||||
@@ -100,10 +148,6 @@ namespace Obi
|
||||
{
|
||||
lengthChange -= m_CursorElement.restLength;
|
||||
|
||||
// if we subtracted the length of the last element, break out of the loop.
|
||||
if (rope.elements.Count == 1)
|
||||
break;
|
||||
|
||||
int index = rope.elements.IndexOf(m_CursorElement);
|
||||
|
||||
if (index >= 0)
|
||||
@@ -121,8 +165,8 @@ namespace Obi
|
||||
|
||||
m_CursorElement = rope.elements[index];
|
||||
}
|
||||
else
|
||||
m_CursorElement = rope.elements[Mathf.Max(0, index - 1)];
|
||||
else
|
||||
m_CursorElement = rope.elements[Mathf.Max(0,index - 1)];
|
||||
}
|
||||
else // negative direction:
|
||||
{
|
||||
@@ -220,69 +264,6 @@ namespace Obi
|
||||
|
||||
// rebuild constraints:
|
||||
rope.RebuildConstraintsFromElements();
|
||||
|
||||
lengthChange = 0;
|
||||
}
|
||||
|
||||
public void UpdateCursor()
|
||||
{
|
||||
rope = GetComponent<ObiRope>();
|
||||
m_CursorElement = null;
|
||||
if (rope.isLoaded)
|
||||
{
|
||||
float elmMu;
|
||||
m_CursorElement = rope.GetElementAt(cursorMu, out elmMu);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSource()
|
||||
{
|
||||
rope = GetComponent<ObiRope>();
|
||||
m_SourceIndex = -1;
|
||||
if (rope.isLoaded)
|
||||
{
|
||||
float elmMu;
|
||||
var elm = rope.GetElementAt(sourceMu, out elmMu);
|
||||
if (elm != null && rope.solver != null)
|
||||
{
|
||||
m_SourceIndex = elmMu < 0.5f ? elm.particle1 : elm.particle2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int AddParticleAt(int index)
|
||||
{
|
||||
int targetIndex = rope.activeParticleCount;
|
||||
|
||||
// Copy data from the particle where we will insert new particles, to the particles we will insert:
|
||||
rope.CopyParticle(rope.solver.particleToActor[m_SourceIndex].indexInActor, targetIndex);
|
||||
|
||||
// Move the new particle to the one at the place where we will insert it:
|
||||
rope.TeleportParticle(targetIndex, rope.solver.positions[rope.solverIndices[index]]);
|
||||
|
||||
// Activate the particle:
|
||||
rope.ActivateParticle();
|
||||
rope.SetRenderingDirty(Oni.RenderingSystemType.AllRopes);
|
||||
|
||||
return rope.solverIndices[targetIndex];
|
||||
}
|
||||
|
||||
private void RemoveParticleAt(int index)
|
||||
{
|
||||
rope.DeactivateParticle(index);
|
||||
rope.SetRenderingDirty(Oni.RenderingSystemType.AllRopes);
|
||||
}
|
||||
|
||||
public float ChangeLength(float lengthChange)
|
||||
{
|
||||
// clamp new length to sane limits:
|
||||
//newLength = Mathf.Clamp(newLength, 0, (rope.sourceBlueprint.particleCount - 1) * rope.ropeBlueprint.interParticleDistance);
|
||||
|
||||
// accumulate length change, we'll reset it to zero after it has been applied.
|
||||
this.lengthChange += lengthChange;
|
||||
|
||||
// return new length:
|
||||
return this.lengthChange + rope.restLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user