flax Engine game engine physics engine joints

Keywords: C++

2021SC@SDUSC

        In the first eight articles, we analyzed the relevant source code under the Actors package of the physical engine in the flax Engine game engine. From this time, we will analyze the source code for the Joints package of the physical engine in the flax Engine game engine. Before analyzing, we should first understand the main functions of the Joints package. Understanding this can help us analyze the source code.

        After consulting the relevant data, we can find that Joints are mainly the physical quantities connecting two objects.

In short, it is the joint used to connect objects.

Five different joints are defined in the flax Engine game engine.

(1) Hinge Joint

        Its function is to bind two rigid bodies together and produce a hinge effect between them

(2) Fixed Joint

         The fixed joint component is used to constrain the motion of one GameObject to another.
         Fixed joints are suitable for situations where you want to easily separate an object from another object, or connect two objects without parent-child relationship to make them move together. The object using fixed joints needs a rigid body component itself.

(3) Spring Joint

         The spring joint assembly connects two rigid bodies together to move like a spring.

   (4) Distance Joint fixed distance joint

        A fixed distance between two rigid bodies.

    (5) D6 Joint: I don't know the specific purpose, and I can't find the relevant content on the Internet. After checking the source code, explain the relevant content.

This analysis analyzes the general framework of the physical system of the flash engine game engine. Next time I will go deep into the source code and analyze the physics engine.

In the next few times, I will analyze the source code for different Joints.

1: HingeJoint:

This time, we will analyze the source code of HingeJoint (hinge joint) in flax Engine game engine and physics engine.

(1) HingeJoint.h file

According to the management, we first analyze the HingeJoint.h file.

API_ENUM(Attributes="Flags") enum class HingeJointFlag
{
    /// <summary>
    /// The none.
    /// </summary>
    None = 0,

    /// <summary>
    /// The joint limit is enabled.
    /// </summary>
    Limit = 0x1,

    /// <summary>
    /// The joint drive is enabled.
    /// </summary>
    Drive = 0x2,
};

The first is the enumeration type class of header file: it defines limit: joint limit and drive: joint drive

DECLARE_SCRIPTING_TYPE_MINIMAL(HingeJointDrive);

    /// <summary>
    /// Target velocity of the joint.
    /// </summary>
    API_FIELD(Attributes="Limit(0)") float Velocity = 0.0f;

    /// <summary>
    /// Maximum torque the drive is allowed to apply.
    /// </summary>
    API_FIELD(Attributes="Limit(0)") float ForceLimit = MAX_float;

    /// <summary>
    /// Scales the velocity of the first body, and its response to drive torque is scaled down.
    /// </summary>
    API_FIELD(Attributes="Limit(0)") float GearRatio = 1.0f;

    /// <summary>
    /// If the joint is moving faster than the drive's target speed, the drive will try to break.
    /// If you don't want the breaking to happen set this to true.
    /// </summary>
    API_FIELD() bool FreeSpin = false;

The second is the constructor of the hinge joint:

Defines:

1: Target speed of joint

2: Maximum torque allowed to be applied by the driver

3: Scale the speed of the first entity and reduce its response to drive torque

4: If the joint moves faster than the drive's target speed, the drive will attempt to disconnect. If you don't want damage to happen, set it to true

public:

    /// <summary>
    /// Compares two objects.
    /// </summary>
    /// <param name="other">The other.</param>
    /// <returns>True if both objects are equal.</returns>
    bool operator==(const HingeJointDrive& other) const
    {
        return Velocity == other.Velocity
                && ForceLimit == other.ForceLimit
                && GearRatio == other.GearRatio
                && FreeSpin && other.FreeSpin;
    }
};

public: compares two objects. True if two objects are equal

DECLARE_SCENE_OBJECT(HingeJoint);
private:

    HingeJointFlag _flags;
    LimitAngularRange _limit;
    HingeJointDrive _drive;

public:

Remove physical joints with all rotational degrees of freedom except a single rotational degree of freedom from its two attached entities, such as a door hinge.

 API_PROPERTY(Attributes="EditorOrder(100), DefaultValue(HingeJointFlag.Limit | HingeJointFlag.Drive)")
    FORCE_INLINE HingeJointFlag GetFlags() const
    {
        return _flags;
    }

Gets the joint mode flag. Control joint behavior.

 API_PROPERTY() void SetFlags(const HingeJointFlag value);

Sets the joint mode flag. Control joint behavior

  API_PROPERTY(Attributes="EditorOrder(110), EditorDisplay(\"Joint\")")
    FORCE_INLINE LimitAngularRange GetLimit() const
    {
        return _limit;
    }

Determine the limits of the joint. Limit constrains motion to a specified range of angles. The limit flag must be enabled on the joint to recognize it.

 API_PROPERTY() void SetDrive(const HingeJointDrive& value);

public:

    /// <summary>
    /// Gets the current angle of the joint (in radians, in the range (-Pi, Pi]).
    /// </summary>
    API_PROPERTY() float GetCurrentAngle() const;

    /// <summary>
    /// Gets the current velocity of the joint.
    /// </summary>
    API_PROPERTY() float GetCurrentVelocity() const;

public:

    // [Joint]
    void Serialize(SerializeStream& stream, const void* otherObj) override;
    void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;

protected:

    // [Joint]
    PxJoint* CreateJoint(JointData& data) override;
};

1: Determines the driving characteristics of the joint. It pushes the angular velocity of the joint to a specific value. The drive flag on the joint must be enabled to activate the drive.

2: Gets the current angle of the joint (in radians, in the range (- Pi, Pi]).

3: Gets the current speed of the joint

(2): HingeJoint.c   file

HingeJoint::HingeJoint(const SpawnParams& params)
    : Joint(params)
    , _flags(HingeJointFlag::Limit | HingeJointFlag::Drive)
{
    _limit.Lower = -90.0f;
    _limit.Upper = 90.0f;
}

Constructor of hinge: set limit and joint

void HingeJoint::SetFlags(const HingeJointFlag value)
{
    if (_flags == value)
        return;

    _flags = value;

    if (_joint)
    {
        auto joint = static_cast<PxRevoluteJoint*>(_joint);
        joint->setRevoluteJointFlag(PxRevoluteJointFlag::eLIMIT_ENABLED, (_flags & HingeJointFlag::Limit) != 0);
        joint->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_ENABLED, (_flags & HingeJointFlag::Drive) != 0);
    }
}

Set Flags:

If flags is equal to value, return. If not, assign value to flags. Initialize joint.

void HingeJoint::SetLimit(const LimitAngularRange& value)
{
    if (_limit == value)
        return;

    _limit = value;

    if (_joint)
    {
        auto joint = static_cast<PxRevoluteJoint*>(_joint);
        PxJointAngularLimitPair limit(value.Lower * DegreesToRadians, value.Upper * DegreesToRadians, value.ContactDist);
        limit.stiffness = value.Spring.Stiffness;
        limit.damping = value.Spring.Damping;
        limit.restitution = value.Restitution;
        joint->setLimit(limit);
    }
}

Set Limit:

If limit is equal to value, return. If not, assign value to limit. Initialize joint.

void HingeJoint::SetDrive(const HingeJointDrive& value)
{
    if (_drive == value)
        return;

    _drive = value;

    if (_joint)
    {
        auto joint = static_cast<PxRevoluteJoint*>(_joint);
        joint->setDriveVelocity(Math::Max(value.Velocity, 0.0f));
        joint->setDriveForceLimit(Math::Max(value.ForceLimit, 0.0f));
        joint->setDriveGearRatio(Math::Max(value.GearRatio, 0.0f));
        joint->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_FREESPIN, value.FreeSpin);
    }
}

Set Drive:

If drive equals value, return. If not, assign value to drive. Initialize joint.

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);
}

Posted by CaseyLiam on Sat, 27 Nov 2021 23:45:28 -0800