Files
FlaxEngine/Source/Engine/Physics/Joints/DistanceJoint.cpp

140 lines
4.0 KiB
C++

// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#include "DistanceJoint.h"
#include "Engine/Physics/PhysicsBackend.h"
#include "Engine/Serialization/Serialization.h"
DistanceJoint::DistanceJoint(const SpawnParams& params)
: Joint(params)
, _flags(DistanceJointFlag::MinDistance | DistanceJointFlag::MaxDistance)
, _minDistance(0.0f)
, _maxDistance(10.0f)
, _tolerance(25.0f)
{
}
void DistanceJoint::SetFlags(DistanceJointFlag value)
{
if (_flags == value)
return;
_flags = value;
if (_joint)
PhysicsBackend::SetDistanceJointFlags(_joint, value);
}
void DistanceJoint::SetMinDistance(float value)
{
value = Math::Clamp(value, 0.0f, _maxDistance);
if (Math::NearEqual(value, _minDistance))
return;
_minDistance = value;
if (_joint)
PhysicsBackend::SetDistanceJointMinDistance(_joint, value);
}
void DistanceJoint::SetMaxDistance(float value)
{
value = Math::Max(_minDistance, value);
if (Math::NearEqual(value, _maxDistance))
return;
_maxDistance = value;
if (_joint)
PhysicsBackend::SetDistanceJointMaxDistance(_joint, value);
}
void DistanceJoint::SetTolerance(float value)
{
value = Math::Max(0.1f, value);
if (Math::NearEqual(value, _tolerance))
return;
_tolerance = value;
if (_joint)
PhysicsBackend::SetDistanceJointTolerance(_joint, value);
}
void DistanceJoint::SetSpringParameters(const SpringParameters& value)
{
if (value == _spring)
return;
_spring = value;
if (_joint)
PhysicsBackend::SetDistanceJointSpring(_joint, value);
}
float DistanceJoint::GetCurrentDistance() const
{
return _joint ? PhysicsBackend::GetDistanceJointDistance(_joint) : 0.0f;
}
#if USE_EDITOR
#include "Engine/Debug/DebugDraw.h"
void DistanceJoint::OnDebugDrawSelected()
{
const Vector3 source = GetPosition();
const Vector3 target = GetTargetPosition();
Vector3 dir = target - source;
const float len = (float)dir.Length();
dir *= 1.0f / len;
Vector3 start = source, end = target;
float max = 0, min = 0;
if (EnumHasAnyFlags(_flags, DistanceJointFlag::MinDistance))
{
min = Math::Min(_minDistance, len);
start += dir * min;
DEBUG_DRAW_LINE(source, start, Color::Red * 0.6f, 0, false);
}
if (EnumHasAnyFlags(_flags, DistanceJointFlag::MaxDistance))
{
max = Math::Min(_maxDistance, len - min);
end -= dir * max;
DEBUG_DRAW_LINE(end, target, Color::Red * 0.6f, 0, false);
}
DEBUG_DRAW_LINE(start, end, Color::Green * 0.6f, 0, false);
// Base
Joint::OnDebugDrawSelected();
}
#endif
void DistanceJoint::Serialize(SerializeStream& stream, const void* otherObj)
{
// Base
Joint::Serialize(stream, otherObj);
SERIALIZE_GET_OTHER_OBJ(DistanceJoint);
SERIALIZE_MEMBER(Flags, _flags);
SERIALIZE_MEMBER(MinDistance, _minDistance);
SERIALIZE_MEMBER(MaxDistance, _maxDistance);
SERIALIZE_MEMBER(Tolerance, _tolerance);
SERIALIZE_MEMBER(Stiffness, _spring.Stiffness);
SERIALIZE_MEMBER(Damping, _spring.Damping);
}
void DistanceJoint::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
// Base
Joint::Deserialize(stream, modifier);
DESERIALIZE_MEMBER(Flags, _flags);
DESERIALIZE_MEMBER(MinDistance, _minDistance);
DESERIALIZE_MEMBER(MaxDistance, _maxDistance);
DESERIALIZE_MEMBER(Tolerance, _tolerance);
DESERIALIZE_MEMBER(Stiffness, _spring.Stiffness);
DESERIALIZE_MEMBER(Damping, _spring.Damping);
}
void* DistanceJoint::CreateJoint(const PhysicsJointDesc& desc)
{
void* joint = PhysicsBackend::CreateDistanceJoint(desc);
PhysicsBackend::SetDistanceJointFlags(joint, _flags);
PhysicsBackend::SetDistanceJointMinDistance(joint, _minDistance);
PhysicsBackend::SetDistanceJointMaxDistance(joint, _maxDistance);
PhysicsBackend::SetDistanceJointTolerance(joint, _tolerance);
PhysicsBackend::SetDistanceJointSpring(joint, _spring);
return joint;
}