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