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

133 lines
4.4 KiB
C++

// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#include "HingeJoint.h"
#include "Engine/Serialization/Serialization.h"
#include "Engine/Physics/PhysicsBackend.h"
HingeJoint::HingeJoint(const SpawnParams& params)
: Joint(params)
, _flags(HingeJointFlag::Limit | HingeJointFlag::Drive)
{
_limit.Lower = -90.0f;
_limit.Upper = 90.0f;
}
void HingeJoint::SetFlags(const HingeJointFlag value)
{
if (_flags == value)
return;
_flags = value;
if (_joint)
PhysicsBackend::SetHingeJointFlags(_joint, value, _drive.FreeSpin);
}
void HingeJoint::SetLimit(const LimitAngularRange& value)
{
if (_limit == value)
return;
_limit = value;
if (_joint)
PhysicsBackend::SetHingeJointLimit(_joint, value);
}
void HingeJoint::SetDrive(const HingeJointDrive& value)
{
if (_drive == value)
return;
_drive = value;
if (_joint)
PhysicsBackend::SetHingeJointDrive(_joint, value);
}
float HingeJoint::GetCurrentAngle() const
{
return _joint ? PhysicsBackend::GetHingeJointAngle(_joint) : 0.0f;
}
float HingeJoint::GetCurrentVelocity() const
{
return _joint ? PhysicsBackend::GetHingeJointVelocity(_joint) : 0.0f;
}
#if USE_EDITOR
#include "Engine/Debug/DebugDraw.h"
#include "Engine/Core/Math/Color.h"
void HingeJoint::OnDebugDrawSelected()
{
const Vector3 source = GetPosition();
const Vector3 target = GetTargetPosition();
const Quaternion xRotation = Quaternion::LookRotation(Vector3::UnitX, Vector3::UnitY);
const Quaternion sourceRotation = GetOrientation() * xRotation;
const Quaternion targetRotation = GetTargetOrientation() * xRotation;
const float size = 15.0f;
const Color color = Color::Green.AlphaMultiplied(0.6f);
DEBUG_DRAW_WIRE_ARROW(source, sourceRotation, size / 100.0f * 0.5f, Color::Red, 0, false);
DEBUG_DRAW_WIRE_ARROW(target, targetRotation, size / 100.0f * 0.5f, Color::Blue, 0, false);
if (EnumHasAnyFlags(_flags, HingeJointFlag::Limit))
{
const float upper = Math::Max(_limit.Upper, _limit.Lower);
const float range = Math::Abs(upper - _limit.Lower);
DEBUG_DRAW_ARC(source, sourceRotation * Quaternion::Euler(0, 0, _limit.Lower - 90.0f), size, range * DegreesToRadians, color, 0, false);
DEBUG_DRAW_WIRE_ARC(source, sourceRotation * Quaternion::Euler(0, 0, upper - 90.0f), size, (360.0f - range) * DegreesToRadians, Color::Red.AlphaMultiplied(0.6f), 0, false);
}
else
{
DEBUG_DRAW_ARC(source, sourceRotation, size, TWO_PI, color, 0, false);
}
DEBUG_DRAW_LINE(source, target, Color::Green * 0.6f, 0, false);
// Base
Joint::OnDebugDrawSelected();
}
#endif
void HingeJoint::Serialize(SerializeStream& stream, const void* otherObj)
{
// Base
Joint::Serialize(stream, otherObj);
SERIALIZE_GET_OTHER_OBJ(HingeJoint);
SERIALIZE_MEMBER(Flags, _flags);
SERIALIZE_MEMBER(ContactDist, _limit.ContactDist);
SERIALIZE_MEMBER(Restitution, _limit.Restitution);
SERIALIZE_MEMBER(Stiffness, _limit.Spring.Stiffness);
SERIALIZE_MEMBER(Damping, _limit.Spring.Damping);
SERIALIZE_MEMBER(LowerLimit, _limit.Lower);
SERIALIZE_MEMBER(UpperLimit, _limit.Upper);
SERIALIZE_MEMBER(Velocity, _drive.Velocity);
SERIALIZE_MEMBER(ForceLimit, _drive.ForceLimit);
SERIALIZE_MEMBER(GearRatio, _drive.GearRatio);
SERIALIZE_MEMBER(FreeSpin, _drive.FreeSpin);
}
void HingeJoint::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
// Base
Joint::Deserialize(stream, modifier);
DESERIALIZE_MEMBER(Flags, _flags);
DESERIALIZE_MEMBER(ContactDist, _limit.ContactDist);
DESERIALIZE_MEMBER(Restitution, _limit.Restitution);
DESERIALIZE_MEMBER(Stiffness, _limit.Spring.Stiffness);
DESERIALIZE_MEMBER(Damping, _limit.Spring.Damping);
DESERIALIZE_MEMBER(LowerLimit, _limit.Lower);
DESERIALIZE_MEMBER(UpperLimit, _limit.Upper);
DESERIALIZE_MEMBER(Velocity, _drive.Velocity);
DESERIALIZE_MEMBER(ForceLimit, _drive.ForceLimit);
DESERIALIZE_MEMBER(GearRatio, _drive.GearRatio);
DESERIALIZE_MEMBER(FreeSpin, _drive.FreeSpin);
}
void* HingeJoint::CreateJoint(const PhysicsJointDesc& desc)
{
void* joint = PhysicsBackend::CreateHingeJoint(desc);
PhysicsBackend::SetHingeJointFlags(joint, _flags, _drive.FreeSpin);
PhysicsBackend::SetHingeJointLimit(joint, _limit);
PhysicsBackend::SetHingeJointDrive(joint, _drive);
return joint;
}