// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Config.h" /// /// Controls spring parameters for a physics joint limits. If a limit is soft (body bounces back due to restitution when /// the limit is reached) the spring will pull the body back towards the limit using the specified parameters. /// API_STRUCT() struct SpringParameters { DECLARE_SCRIPTING_TYPE_MINIMAL(SpringParameters); /// /// The spring strength. Force proportional to the position error. /// API_FIELD() float Stiffness; /// /// Damping strength. Force proportional to the velocity error. /// API_FIELD() float Damping; public: /// /// Constructs a spring with no force. /// SpringParameters() { Stiffness = 0.0f; Damping = 0.0f; } /// /// Constructs a spring. /// /// Spring strength. Force proportional to the position error. /// Damping strength. Force proportional to the velocity error. SpringParameters(const float stiffness, const float damping) : Stiffness(stiffness) , Damping(damping) { } public: bool operator==(const SpringParameters& other) const { return Stiffness == other.Stiffness && Damping == other.Damping; } }; /// /// Represents a joint limit between two distance values. Lower value must be less than the upper value. /// API_STRUCT() struct LimitLinearRange { DECLARE_SCRIPTING_TYPE_MINIMAL(LimitLinearRange); /// /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. /// API_FIELD() float ContactDist = -1.0f; /// /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. /// API_FIELD(Attributes="Limit(0.0f, 1.0f)") float Restitution = 0.0f; /// /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// API_FIELD() SpringParameters Spring; /// /// The lower distance of the limit. Must be less than upper. /// API_FIELD() float Lower = 0.0f; /// /// The upper distance of the limit. Must be more than lower. /// API_FIELD() float Upper = 0.0f; public: /// /// Constructs an empty limit. /// LimitLinearRange() { } /// /// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop. /// /// The lower distance of the limit. Must be less than upper. /// The upper distance of the limit. Must be more than lower. /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. Specify -1 for the default. LimitLinearRange(const float lower, const float upper, const float contactDist = -1.0f) : ContactDist(contactDist) , Lower(lower) , Upper(upper) { } /// /// Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the restitution parameter and will be pulled back towards the limit by the provided spring. /// /// The lower distance of the limit. Must be less than upper. /// The upper distance of the limit. Must be more than lower. /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. LimitLinearRange(const float lower, const float upper, const SpringParameters& spring, const float restitution = 0.0f) : Restitution(restitution) , Spring(spring) , Lower(lower) , Upper(upper) { } public: bool operator==(const LimitLinearRange& other) const { return Lower == other.Lower && Upper == other.Upper && ContactDist == other.ContactDist && Restitution == other.Restitution && Spring == other.Spring; } }; /// /// Represents a joint limit between zero a single distance value. /// API_STRUCT() struct LimitLinear { DECLARE_SCRIPTING_TYPE_MINIMAL(LimitLinear); /// /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. /// API_FIELD() float ContactDist = -1.0f; /// /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. /// API_FIELD(Attributes="Limit(0.0f, 1.0f)") float Restitution = 0.0f; /// /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// API_FIELD() SpringParameters Spring; /// /// The distance at which the limit becomes active. /// API_FIELD() float Extent = 0.0f; public: /// /// Constructs an empty limit. /// LimitLinear() { } /// /// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop. /// /// The distance at which the limit becomes active. /// The distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. Specify -1 for the default. LimitLinear(const float extent, const float contactDist = -1.0f) : ContactDist(contactDist) , Extent(extent) { } /// /// Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the restitution parameter and will be pulled back towards the limit by the provided spring. /// /// The distance at which the limit becomes active. /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. LimitLinear(const float extent, const SpringParameters& spring, const float restitution = 0.0f) : Restitution(restitution) , Spring(spring) , Extent(extent) { } public: bool operator==(const LimitLinear& other) const { return Extent == other.Extent && ContactDist == other.ContactDist && Restitution == other.Restitution && Spring == other.Spring; } }; /// /// Represents a joint limit between two angles. /// API_STRUCT() struct LimitAngularRange { DECLARE_SCRIPTING_TYPE_MINIMAL(LimitAngularRange); /// /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. /// API_FIELD() float ContactDist = -1.0f; /// /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. /// API_FIELD(Attributes="Limit(0.0f, 1.0f)") float Restitution = 0.0f; /// /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// API_FIELD() SpringParameters Spring; /// /// Lower angle of the limit (in degrees). Must be less than upper. /// API_FIELD() float Lower = 0.0f; /// /// Upper angle of the limit (in degrees). Must be less than lower. /// API_FIELD() float Upper = 0.0f; public: /// /// Constructs an empty limit. /// LimitAngularRange() { } /// /// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop. /// /// The lower angle of the limit (in degrees). Must be less than upper. /// The upper angle of the limit (in degrees). Must be more than lower. /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. Specify -1 for the default. LimitAngularRange(const float lower, const float upper, const float contactDist = -1.0f) : ContactDist(contactDist) , Lower(lower) , Upper(upper) { } /// /// Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the restitution parameter and will be pulled back towards the limit by the provided spring. /// /// The lower angle of the limit. Must be less than upper. /// The upper angle of the limit. Must be more than lower. /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. LimitAngularRange(const float lower, const float upper, const SpringParameters& spring, const float restitution = 0.0f) : Restitution(restitution) , Spring(spring) , Lower(lower) , Upper(upper) { } public: bool operator==(const LimitAngularRange& other) const { return Lower == other.Lower && Upper == other.Upper && ContactDist == other.ContactDist && Restitution == other.Restitution && Spring == other.Spring; } }; /// /// Represents a joint limit that constraints movement to within an elliptical cone. /// API_STRUCT() struct LimitConeRange { DECLARE_SCRIPTING_TYPE_MINIMAL(LimitConeRange); /// /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. /// API_FIELD() float ContactDist = -1.0f; /// /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. /// API_FIELD(Attributes="Limit(0.0f, 1.0f)") float Restitution = 0.0f; /// /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// API_FIELD() SpringParameters Spring; /// /// The Y angle of the cone (in degrees). Movement is constrained between 0 and this angle on the Y axis. /// API_FIELD(Attributes="Limit(0.0f, 180.0f)") float YLimitAngle = 90.0f; /// /// The Z angle of the cone (in degrees). Movement is constrained between 0 and this angle on the Z axis. /// API_FIELD(Attributes="Limit(0.0f, 180.0f)") float ZLimitAngle = 90.0f; public: /// /// Constructs a limit with a 45 degree cone. /// LimitConeRange() { } /// /// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop. /// /// The Y angle of the cone (in degrees). Movement is constrained between 0 and this angle on the Y axis. /// The Z angle of the cone (in degrees). Movement is constrained between 0 and this angle on the Z axis. /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is reached to avoid breaking the limit. Specify -1 for the default. LimitConeRange(const float yLimitAngle, const float zLimitAngle, const float contactDist = -1.0f) : ContactDist(contactDist) , YLimitAngle(yLimitAngle) , ZLimitAngle(zLimitAngle) { } /// /// Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the restitution parameter and will be pulled back towards the limit by the provided spring. /// /// The Y angle of the cone (in degrees). Movement is constrained between 0 and this angle on the Y axis. /// The Z angle of the cone (in degrees). Movement is constrained between 0 and this angle on the Z axis. /// The spring that controls how are the bodies pulled back towards the limit when they breach it. /// Controls how do objects react when the limit is reached, values closer to zero specify non-elastic collision, while those closer to one specify more elastic (i.e bouncy) collision. Must be in [0, 1] range. LimitConeRange(const float yLimitAngle, const float zLimitAngle, const SpringParameters& spring, const float restitution = 0.0f) : Restitution(restitution) , Spring(spring) , YLimitAngle(yLimitAngle) , ZLimitAngle(zLimitAngle) { } public: bool operator==(const LimitConeRange& other) const { return YLimitAngle == other.YLimitAngle && ZLimitAngle == other.ZLimitAngle && ContactDist == other.ContactDist && Restitution == other.Restitution && Spring == other.Spring; } };