Fixes and tweaks to SplineRopeBody
This commit is contained in:
@@ -19,10 +19,6 @@ void SplineRopeBody::Tick()
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
|
||||
// TODO: add as configs
|
||||
const float SubstepTime = 0.02f;
|
||||
const int32 SolverIterations = 1;
|
||||
|
||||
// Cache data
|
||||
const Vector3 gravity = Physics::GetGravity() * GravityScale;
|
||||
auto& keyframes = _spline->Curve.GetKeyframes();
|
||||
@@ -92,17 +88,40 @@ void SplineRopeBody::Tick()
|
||||
}
|
||||
}
|
||||
|
||||
// Constraints solving
|
||||
for (int32 iteration = 0; iteration < SolverIterations; iteration++)
|
||||
// Distance constraint
|
||||
for (int32 i = 1; i < keyframesCount; i++)
|
||||
{
|
||||
// Distance constraint
|
||||
for (int32 i = 1; i < keyframesCount; i++)
|
||||
auto& massA = _masses[i - 1];
|
||||
auto& massB = _masses[i];
|
||||
Vector3 offset = massB.Position - massA.Position;
|
||||
const float distance = offset.Length();
|
||||
const float scale = (distance - massB.SegmentLength) / Math::Max(distance, ZeroTolerance);
|
||||
if (massA.Unconstrained && massB.Unconstrained)
|
||||
{
|
||||
auto& massA = _masses[i - 1];
|
||||
offset *= scale * 0.5f;
|
||||
massA.Position += offset;
|
||||
massB.Position -= offset;
|
||||
}
|
||||
else if (massA.Unconstrained)
|
||||
{
|
||||
massA.Position += scale * offset;
|
||||
}
|
||||
else if (massB.Unconstrained)
|
||||
{
|
||||
massB.Position -= scale * offset;
|
||||
}
|
||||
}
|
||||
|
||||
// Stiffness constraint
|
||||
if (EnableStiffness)
|
||||
{
|
||||
for (int32 i = 2; i < keyframesCount; i++)
|
||||
{
|
||||
auto& massA = _masses[i - 2];
|
||||
auto& massB = _masses[i];
|
||||
Vector3 offset = massB.Position - massA.Position;
|
||||
const float distance = offset.Length();
|
||||
const float scale = (distance - massB.SegmentLength) / Math::Max(distance, ZeroTolerance);
|
||||
const float scale = (distance - massB.SegmentLength * 2.0f) / Math::Max(distance, ZeroTolerance);
|
||||
if (massA.Unconstrained && massB.Unconstrained)
|
||||
{
|
||||
offset *= scale * 0.5f;
|
||||
@@ -118,33 +137,6 @@ void SplineRopeBody::Tick()
|
||||
massB.Position -= scale * offset;
|
||||
}
|
||||
}
|
||||
|
||||
// Stiffness constraint
|
||||
if (EnableStiffness)
|
||||
{
|
||||
for (int32 i = 2; i < keyframesCount; i++)
|
||||
{
|
||||
auto& massA = _masses[i - 2];
|
||||
auto& massB = _masses[i];
|
||||
Vector3 offset = massB.Position - massA.Position;
|
||||
const float distance = offset.Length();
|
||||
const float scale = (distance - massB.SegmentLength * 2.0f) / Math::Max(distance, ZeroTolerance);
|
||||
if (massA.Unconstrained && massB.Unconstrained)
|
||||
{
|
||||
offset *= scale * 0.5f;
|
||||
massA.Position += offset;
|
||||
massB.Position -= offset;
|
||||
}
|
||||
else if (massA.Unconstrained)
|
||||
{
|
||||
massA.Position += scale * offset;
|
||||
}
|
||||
else if (massB.Unconstrained)
|
||||
{
|
||||
massB.Position -= scale * offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_time -= substepTime;
|
||||
@@ -161,31 +153,9 @@ void SplineRopeBody::Tick()
|
||||
}
|
||||
}
|
||||
|
||||
void SplineRopeBody::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
{
|
||||
Actor::Serialize(stream, otherObj);
|
||||
|
||||
SERIALIZE_GET_OTHER_OBJ(SplineRopeBody);
|
||||
|
||||
SERIALIZE(AttachEnd);
|
||||
SERIALIZE(GravityScale);
|
||||
SERIALIZE(AdditionalForce);
|
||||
SERIALIZE(EnableStiffness);
|
||||
}
|
||||
|
||||
void SplineRopeBody::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
{
|
||||
Actor::Deserialize(stream, modifier);
|
||||
|
||||
DESERIALIZE(AttachEnd);
|
||||
DESERIALIZE(GravityScale);
|
||||
DESERIALIZE(AdditionalForce);
|
||||
DESERIALIZE(EnableStiffness);
|
||||
}
|
||||
|
||||
void SplineRopeBody::OnEnable()
|
||||
{
|
||||
GetScene()->Ticking.Update.AddTick<SplineRopeBody, &SplineRopeBody::Tick>(this);
|
||||
GetScene()->Ticking.FixedUpdate.AddTick<SplineRopeBody, &SplineRopeBody::Tick>(this);
|
||||
|
||||
Actor::OnEnable();
|
||||
}
|
||||
@@ -194,7 +164,7 @@ void SplineRopeBody::OnDisable()
|
||||
{
|
||||
Actor::OnDisable();
|
||||
|
||||
GetScene()->Ticking.Update.RemoveTick(this);
|
||||
GetScene()->Ticking.FixedUpdate.RemoveTick(this);
|
||||
}
|
||||
|
||||
void SplineRopeBody::OnParentChanged()
|
||||
|
||||
@@ -13,6 +13,7 @@ class Spline;
|
||||
/// <seealso cref="Spline" />
|
||||
API_CLASS() class FLAXENGINE_API SplineRopeBody : public Actor
|
||||
{
|
||||
API_AUTO_SERIALIZATION();
|
||||
DECLARE_SCENE_OBJECT(SplineRopeBody);
|
||||
private:
|
||||
|
||||
@@ -54,6 +55,12 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(30), EditorDisplay(\"Rope\")")
|
||||
bool EnableStiffness = false;
|
||||
|
||||
/// <summary>
|
||||
/// The rope simulation update substep (in seconds). Defines the frequency of physics update.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(40), Limit(0, 0.1f, 0.0001f), EditorDisplay(\"Rope\")")
|
||||
float SubstepTime = 0.02f;
|
||||
|
||||
private:
|
||||
|
||||
void Tick();
|
||||
@@ -61,8 +68,6 @@ private:
|
||||
public:
|
||||
|
||||
// [Actor]
|
||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||
void OnEnable() override;
|
||||
void OnDisable() override;
|
||||
void OnTransformChanged() override;
|
||||
|
||||
Reference in New Issue
Block a user