(九)flax Engine 游戏引擎物理引擎joints(关节)

2021SC@SDUSC

        前八次文章我们分析了flax Engine 游戏引擎中物理引擎的Actors(角色)包下的相关的源码的分析,从本次开始我们将针对flax Engine 游戏引擎中的物理引擎中的Joints(关节)这个包进行,源码的分析。在分析之前我们先要了解一下Joints(关节)这个包主要的功能是什么,了解这个以后可以对我们分析源码起到不小的帮助。

        在查阅相关资料后我们可以发现:Joints (关节)主要是针对两个物体间进行连接的物理量。

简而言之就是用来连接物体的关节。

在flax Engine 游戏引擎中定了5种不同的joints(关节)。

(1)Hinge Joint 铰链关节

        其作用是将两个刚体束缚在一起,在两者之间产生铰链效果

(2)Fixed Joint 固定关节

        固定关节组件用于约束一个游戏对象对另一个游戏对象的运动。
        固定关节适用于以下的情形:当希望将对象较容易与另—个对象分开时,或者连接两个没有父子关系的对象使其一起运动,使用固定关节的对象自身需要有—个刚体组件。

(3)Spring Joint 弹簧关节

        弹簧关节组件可将两个刚体连接在—起,使其像连接着弹簧那样运动。

  (4) Distance Joint 固定距离关节

        两个刚体之间固定距离。

   (5)D6 Joint :不知道具体用途在网上也找不到相关内容,在之后查看源码后,进行相关内容的解释。

本次分析就flaxengine 游戏引擎的物理系统的大致框架来进行分析。下次我将深入源代码进行物理引擎的分析。

在接下来的几次种,我将针对不同的Joints(关节)进行源码的分析。

一:HingeJoint(铰链关节):

本次我们将针对flax Engine 游戏引擎物理引擎中的HingeJoint(铰链关节)进行源码的分析。

(1)HingeJoint.h 文件

按照管理我们首先分析HingeJoint.h文件。

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

首先是头文件的枚举类型的类:定义了limit:关节限制和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;

其次是铰链关节的构造函数:

定义了:

1:关节的目标速度

2:驱动器允许施加的最大扭矩

3:缩放第一个实体的速度,并缩小其对驱动扭矩的响应

4:如果关节的移动速度超过驱动器的目标速度,驱动器将尝试断开。如果你不想破坏发生,将其设置为真

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:比较两个对象。如果两个对象相等,则为True

DECLARE_SCENE_OBJECT(HingeJoint);
private:

    HingeJointFlag _flags;
    LimitAngularRange _limit;
    HingeJointDrive _drive;

public:

从其两个附着的实体(例如门铰链)移除除单个旋转*度以外的所有旋转*度的物理关节。

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

获取关节模式标志。控制联合行为。

 API_PROPERTY() void SetFlags(const HingeJointFlag value);

设置关节模式标志。控制联合行为

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

确定关节的限制。“限制”将运动约束到指定的角度范围。必须在关节上启用限制标志才能识别该标记。

 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:确定关节的驱动特性。它会将关节的角速度推向特定值。必须启用关节上的驱动标志,才能激活驱动。

2:获取关节的当前角度(以弧度为单位,范围为(-Pi,Pi])。

3:获取关节的当前速度

(2):HingeJoint.c 文件

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

铰链的构造函数:设置limit 和 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);
    }
}

设置Flags:

如果flags等于value 则返回,如果不是则将value赋值给flags。初始化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);
    }
}

设置Limit:

如果limit等于value 则返回,如果不是则将value赋值给limit。初始化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);
    }
}

设置Drive:

如果drive等于value 则返回,如果不是则将value赋值给drive。初始化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);
}

上一篇:881. Boats to Save People(救生船)———附带思路和完整代码


下一篇:jQuery 学习系列笔记(三)(续)