// Copyright (c) 2018-2019 Kiwano - Nomango // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include namespace kiwano { namespace physics { KGE_DECLARE_SMART_PTR(Joint); KGE_DECLARE_SMART_PTR(DistanceJoint); KGE_DECLARE_SMART_PTR(FrictionJoint); KGE_DECLARE_SMART_PTR(GearJoint); KGE_DECLARE_SMART_PTR(MotorJoint); KGE_DECLARE_SMART_PTR(MouseJoint); KGE_DECLARE_SMART_PTR(PrismaticJoint); KGE_DECLARE_SMART_PTR(PulleyJoint); KGE_DECLARE_SMART_PTR(RevoluteJoint); KGE_DECLARE_SMART_PTR(RopeJoint); KGE_DECLARE_SMART_PTR(WeldJoint); KGE_DECLARE_SMART_PTR(WheelJoint); /** * \addtogroup Physics * @{ */ /// \~chinese /// @brief 关节 class KGE_API Joint : public virtual ObjectBase { public: /// \~chinese /// @brief 关节类型 enum class Type { Unknown = 0, ///< 未知 Revolute, ///< 旋转关节 Prismatic, ///< 平移关节 Distance, ///< 固定距离关节 Pulley, ///< 滑轮关节 Mouse, ///< 鼠标关节 Gear, ///< 齿轮关节 Wheel, ///< 轮关节 Weld, ///< 焊接关节 Friction, ///< 摩擦关节 Rope, ///< 绳关节 Motor ///< 马达关节 }; /// \~chinese /// @brief 关节基础参数 struct ParamBase { Body* body_a; ///< 关节连接的物体A Body* body_b; ///< 关节连接的物体B ParamBase(Body* body_a, Body* body_b) : body_a(body_a) , body_b(body_b) { } ParamBase(BodyPtr body_a, BodyPtr body_b) : body_a(body_a.get()) , body_b(body_b.get()) { } }; Joint(); virtual ~Joint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, b2JointDef* joint_def); /// \~chinese /// @brief 获取关节连接的物体A BodyPtr GetBodyA() const; /// \~chinese /// @brief 获取关节连接的物体B BodyPtr GetBodyB() const; /// \~chinese /// @brief 获取物理世界 World* GetWorld() const; /// \~chinese /// @brief 销毁关节 void Destroy(); b2Joint* GetB2Joint() const; void SetB2Joint(b2Joint* joint); private: b2Joint* joint_; World* world_; Type type_; }; /// \~chinese /// @brief 固定距离关节 class KGE_API DistanceJoint : public Joint { public: /// \~chinese /// @brief 固定距离关节参数 struct Param : public Joint::ParamBase { Point anchor_a; ///< 关节在物体A上的连接点 Point anchor_b; ///< 关节在物体B上的连接点 float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固 float damping_ratio; ///< 阻尼率,值越大关节运动阻尼越大 Param(Body* body_a, Body* body_b, Point const& anchor_a, Point const& anchor_b, float frequency_hz = 0.f, float damping_ratio = 0.f) : ParamBase(body_a, body_b) , anchor_a(anchor_a) , anchor_b(anchor_b) , frequency_hz(frequency_hz) , damping_ratio(damping_ratio) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor_a, Point const& anchor_b, float frequency_hz = 0.f, float damping_ratio = 0.f) : Param(body_a.get(), body_b.get(), anchor_a, anchor_b, frequency_hz, damping_ratio) { } }; /// \~chinese /// @brief 创建固定距离关节 /// @param world 物理世界 /// @param param 关节参数 static DistanceJointPtr Create(World* world, Param const& param); DistanceJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 设置关节长度 void SetLength(float length); /// \~chinese /// @brief 获取关节长度 float GetLength() const; /// \~chinese /// @brief 设置弹簧响应速度 [赫兹] void SetFrequency(float hz); /// \~chinese /// @brief 获取弹簧响应速度 [赫兹] float GetFrequency() const; /// \~chinese /// @brief 设置阻尼率 void SetDampingRatio(float ratio); /// \~chinese /// @brief 获取阻尼率 float GetDampingRatio() const; private: b2DistanceJoint* raw_joint_; }; /// \~chinese /// @brief 摩擦关节 class KGE_API FrictionJoint : public Joint { public: struct Param : public Joint::ParamBase { Point anchor; ///< 摩擦作用点 float max_force; ///< 最大摩擦力 float max_torque; ///< 最大扭力 Param(Body* body_a, Body* body_b, Point const& anchor, float max_force = 0.f, float max_torque = 0.f) : ParamBase(body_a, body_b) , anchor(anchor) , max_force(max_force) , max_torque(max_torque) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, float max_force = 0.f, float max_torque = 0.f) : Param(body_a.get(), body_b.get(), anchor, max_force, max_torque) { } }; /// \~chinese /// @brief 创建摩擦关节 /// @param world 物理世界 /// @param param 关节参数 static FrictionJointPtr Create(World* world, Param const& param); FrictionJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 设置最大摩擦力 void SetMaxForce(float force); /// \~chinese /// @brief 获取最大摩擦力 float GetMaxForce() const; /// \~chinese /// @brief 设置最大转矩 void SetMaxTorque(float torque); /// \~chinese /// @brief 获取最大转矩 float GetMaxTorque() const; private: b2FrictionJoint* raw_joint_; }; /// \~chinese /// @brief 齿轮关节 class KGE_API GearJoint : public Joint { public: /// \~chinese /// @brief 齿轮关节参数 struct Param : public Joint::ParamBase { Joint* joint_a; ///< 关节A(旋转关节/平移关节) Joint* joint_b; ///< 关节B(旋转关节/平移关节) float ratio; ///< 齿轮传动比 Param(Joint* joint_a, Joint* joint_b, float ratio = 1.f) : ParamBase(nullptr, nullptr) , joint_a(joint_a) , joint_b(joint_b) , ratio(ratio) { } Param(JointPtr joint_a, JointPtr joint_b, float ratio = 1.f) : Param(joint_a.get(), joint_b.get(), ratio) { } }; /// \~chinese /// @brief 创建齿轮关节 /// @param world 物理世界 /// @param param 关节参数 static GearJointPtr Create(World* world, Param const& param); GearJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 设定齿轮传动比 void SetRatio(float ratio); /// \~chinese /// @brief 获取齿轮传动比 float GetRatio() const; private: b2GearJoint* raw_joint_; }; /// \~chinese /// @brief 马达关节 class KGE_API MotorJoint : public Joint { public: /// \~chinese /// @brief 马达关节参数 struct Param : public Joint::ParamBase { float max_force; ///< 最大摩擦力 float max_torque; ///< 最大转矩 float correction_factor; ///< 位置矫正因子(范围 0-1) Param(Body* body_a, Body* body_b, float max_force = 1.f, float max_torque = 100.f, float correction_factor = 0.3f) : ParamBase(body_a, body_b) , max_force(max_force) , max_torque(max_torque) , correction_factor(correction_factor) { } Param(BodyPtr body_a, BodyPtr body_b, float max_force = 0.f, float max_torque = 0.f, float correction_factor = 0.3f) : Param(body_a.get(), body_b.get(), max_force, max_torque, correction_factor) { } }; /// \~chinese /// @brief 创建马达关节 /// @param world 物理世界 /// @param param 关节参数 static MotorJointPtr Create(World* world, Param const& param); MotorJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 设置最大摩擦力 void SetMaxForce(float force); /// \~chinese /// @brief 获取最大摩擦力 float GetMaxForce() const; /// \~chinese /// @brief 设置最大转矩 void SetMaxTorque(float torque); /// \~chinese /// @brief 获取最大转矩 float GetMaxTorque() const; private: b2MotorJoint* raw_joint_; }; /// \~chinese /// @brief 平移关节 class KGE_API PrismaticJoint : public Joint { public: /// \~chinese /// @brief 平移关节参数 struct Param : public Joint::ParamBase { Point anchor; ///< 关节位置 Vec2 axis; ///< 物体A滑动的方向 bool enable_limit; ///< 是否启用限制 float lower_translation; ///< 移动的最小限制,与方向同向为正,反向为负,启用限制后才有效果 float upper_translation; ///< 移动的最大限制,与方向同向为正,反向为负,启用限制后才有效果 bool enable_motor; ///< 是否启用马达 float max_motor_force; ///< 最大马达力 [N] float motor_speed; ///< 马达转速 [degree/s] Param(Body* body_a, Body* body_b, Point const& anchor, Vec2 const& axis, bool enable_limit = false, float lower_translation = 0.0f, float upper_translation = 0.0f, bool enable_motor = false, float max_motor_force = 0.0f, float motor_speed = 0.0f) : ParamBase(body_a, body_b) , anchor(anchor) , axis(axis) , enable_limit(enable_limit) , lower_translation(lower_translation) , upper_translation(upper_translation) , enable_motor(enable_motor) , max_motor_force(max_motor_force) , motor_speed(motor_speed) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, Vec2 const& axis, bool enable_limit = false, float lower_translation = 0.0f, float upper_translation = 0.0f, bool enable_motor = false, float max_motor_force = 0.0f, float motor_speed = 0.0f) : Param(body_a.get(), body_b.get(), anchor, axis, enable_limit, lower_translation, upper_translation, enable_motor, max_motor_force, motor_speed) { } }; /// \~chinese /// @brief 创建平移关节 /// @param world 物理世界 /// @param param 关节参数 static PrismaticJointPtr Create(World* world, Param const& param); PrismaticJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 获取参考角 float GetReferenceAngle() const; /// \~chinese /// @brief 获取关节转换 float GetJointTranslation() const; /// \~chinese /// @brief 获取关节速度 float GetJointSpeed() const; /// \~chinese /// @brief 是否启用关节限制 bool IsLimitEnabled() const; /// \~chinese /// @brief 设置是否启用关节限制 void EnableLimit(bool flag); /// \~chinese /// @brief 获取平移最小限制 float GetLowerLimit() const; /// \~chinese /// @brief 获取平移最大限制 float GetUpperLimit() const; /// \~chinese /// @brief 设置关节限制 void SetLimits(float lower, float upper); /// \~chinese /// @brief 是否启用马达 bool IsMotorEnabled() const; /// \~chinese /// @brief 设置是否启用马达 void EnableMotor(bool flag); /// \~chinese /// @brief 设置马达转速 [degree/s] void SetMotorSpeed(float speed); /// \~chinese /// @brief 获取马达转速 [degree/s] float GetMotorSpeed() const; /// \~chinese /// @brief 设置最大马达力 [N] void SetMaxMotorForce(float force); /// \~chinese /// @brief 获取最大马达力 [N] float GetMaxMotorForce() const; private: b2PrismaticJoint* raw_joint_; }; /// \~chinese /// @brief 滑轮关节 class KGE_API PulleyJoint : public Joint { public: /// \~chinese /// @brief 滑轮关节参数 struct Param : public Joint::ParamBase { Point anchor_a; ///< 关节在物体A上的作用点 Point anchor_b; ///< 关节在物体B上的作用点 Point ground_anchor_a; ///< 物体A对应的滑轮的位置 Point ground_anchor_b; ///< 物体B对应的滑轮的位置 float ratio; ///< 滑轮比,关节传动时,滑轮上升和下降的两头的位移比例 Param(Body* body_a, Body* body_b, Point const& anchor_a, Point const& anchor_b, Point const& ground_anchor_a, Point const& ground_anchor_b, float ratio = 1.0f) : ParamBase(body_a, body_b) , anchor_a(anchor_a) , anchor_b(anchor_b) , ground_anchor_a(ground_anchor_a) , ground_anchor_b(ground_anchor_b) , ratio(ratio) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor_a, Point const& anchor_b, Point const& ground_anchor_a, Point const& ground_anchor_b, float ratio = 1.0f) : Param(body_a.get(), body_b.get(), anchor_a, anchor_b, ground_anchor_a, ground_anchor_b, ratio) { } }; /// \~chinese /// @brief 创建滑轮关节 /// @param world 物理世界 /// @param param 关节参数 static PulleyJointPtr Create(World* world, Param const& param); PulleyJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 物体A对应的滑轮的位置 Point GetGroundAnchorA() const; /// \~chinese /// @brief 物体B对应的滑轮的位置 Point GetGroundAnchorB() const; /// \~chinese /// @brief 获取滑轮传动比 float GetRatio() const; /// \~chinese /// @brief 获取物体A与滑轮的距离 float GetLengthA() const; /// \~chinese /// @brief 获取物体B与滑轮的距离 float GetLengthB() const; /// \~chinese /// @brief 获取物体A与滑轮的当前距离 float GetCurrentLengthA() const; /// \~chinese /// @brief 获取物体B与滑轮的当前距离 float GetCurrentLengthB() const; private: b2PulleyJoint* raw_joint_; }; /// \~chinese /// @brief 旋转关节 class KGE_API RevoluteJoint : public Joint { public: /// \~chinese /// @brief 旋转关节参数 struct Param : public Joint::ParamBase { Point anchor; ///< 关节位置 bool enable_limit; ///< 是否启用限制 float lower_angle; ///< 移动的最小限制,与方向同向为正,反向为负,启用限制后才有效果 float upper_angle; ///< 移动的最大限制,与方向同向为正,反向为负,启用限制后才有效果 bool enable_motor; ///< 是否启用马达 float max_motor_torque; ///< 最大马达力 [N] float motor_speed; ///< 马达转速 [degree/s] Param(Body* body_a, Body* body_b, Point const& anchor, bool enable_limit = false, float lower_angle = 0.0f, float upper_angle = 0.0f, bool enable_motor = false, float max_motor_torque = 0.0f, float motor_speed = 0.0f) : ParamBase(body_a, body_b) , anchor(anchor) , enable_limit(enable_limit) , lower_angle(lower_angle) , upper_angle(upper_angle) , enable_motor(enable_motor) , max_motor_torque(max_motor_torque) , motor_speed(motor_speed) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, bool enable_limit = false, float lower_angle = 0.0f, float upper_angle = 0.0f, bool enable_motor = false, float max_motor_torque = 0.0f, float motor_speed = 0.0f) : Param(body_a.get(), body_b.get(), anchor, enable_limit, lower_angle, upper_angle, enable_motor, max_motor_torque, motor_speed) { } }; /// \~chinese /// @brief 创建旋转关节 /// @param world 物理世界 /// @param param 关节参数 static RevoluteJointPtr Create(World* world, Param const& param); RevoluteJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 获取参考角 float GetReferenceAngle() const; /// \~chinese /// @brief 获取关节角度 float GetJointAngle() const; /// \~chinese /// @brief 获取关节速度 float GetJointSpeed() const; /// \~chinese /// @brief 是否启用关节限制 bool IsLimitEnabled() const; /// \~chinese /// @brief 设置是否启用关节限制 void EnableLimit(bool flag); /// \~chinese /// @brief 获取平移最小限制 float GetLowerLimit() const; /// \~chinese /// @brief 获取平移最大限制 float GetUpperLimit() const; /// \~chinese /// @brief 设置关节限制 void SetLimits(float lower, float upper); /// \~chinese /// @brief 是否启用马达 bool IsMotorEnabled() const; /// \~chinese /// @brief 设置是否启用马达 void EnableMotor(bool flag); /// \~chinese /// @brief 设置马达转速 [degree/s] void SetMotorSpeed(float speed); /// \~chinese /// @brief 获取马达转速 [degree/s] float GetMotorSpeed() const; /// \~chinese /// @brief 设置最大马达转矩 [N/m] void SetMaxMotorTorque(float torque); /// \~chinese /// @brief 获取最大马达转矩 [N/m] float GetMaxMotorTorque() const; private: b2RevoluteJoint* raw_joint_; }; /// \~chinese /// @brief 绳关节 class KGE_API RopeJoint : public Joint { public: /// \~chinese /// @brief 绳关节参数 struct Param : public Joint::ParamBase { Point local_anchor_a; ///< 关节在物体A上的连接点 Point local_anchor_b; ///< 关节在物体B上的连接点 float max_length; ///< 绳索最大长度 Param(Body* body_a, Body* body_b, Point const& local_anchor_a, Point const& local_anchor_b, float max_length = 0.f) : ParamBase(body_a, body_b) , local_anchor_a(local_anchor_a) , local_anchor_b(local_anchor_b) , max_length(max_length) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& local_anchor_a, Point const& local_anchor_b, float max_length = 0.f) : Param(body_a.get(), body_b.get(), local_anchor_a, local_anchor_b, max_length) { } }; /// \~chinese /// @brief 创建绳关节 /// @param world 物理世界 /// @param param 关节参数 static RopeJointPtr Create(World* world, Param const& param); RopeJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 设置关节最大长度 void SetMaxLength(float length); /// \~chinese /// @brief 获取关节最大长度 float GetMaxLength() const; private: b2RopeJoint* raw_joint_; }; /// \~chinese /// @brief 焊接关节 class KGE_API WeldJoint : public Joint { public: /// \~chinese /// @brief 焊接关节参数 struct Param : public Joint::ParamBase { Point anchor; ///< 焊接位置 float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固 float damping_ratio; ///< 阻尼率,值越大关节运动阻尼越大 Param(Body* body_a, Body* body_b, Point const& anchor, float frequency_hz = 0.f, float damping_ratio = 0.f) : ParamBase(body_a, body_b) , anchor(anchor) , frequency_hz(frequency_hz) , damping_ratio(damping_ratio) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, float frequency_hz = 0.f, float damping_ratio = 0.f) : Param(body_a.get(), body_b.get(), anchor, frequency_hz, damping_ratio) { } }; /// \~chinese /// @brief 创建焊接关节 /// @param world 物理世界 /// @param param 关节参数 static WeldJointPtr Create(World* world, Param const& param); WeldJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 获取物体B相对于物体A的角度 float GetReferenceAngle() const; /// \~chinese /// @brief 设置弹簧响应速度 [赫兹] void SetFrequency(float hz); /// \~chinese /// @brief 获取弹簧响应速度 [赫兹] float GetFrequency() const; /// \~chinese /// @brief 设置阻尼率 void SetDampingRatio(float ratio); /// \~chinese /// @brief 获取阻尼率 float GetDampingRatio() const; private: b2WeldJoint* raw_joint_; }; /// \~chinese /// @brief 轮关节 class KGE_API WheelJoint : public Joint { public: /// \~chinese /// @brief 轮关节参数 struct Param : public Joint::ParamBase { Point anchor; ///< 轮关节位置 Vec2 axis; ///< 物体A滑动方向 bool enable_motor; ///< 是否启用马达 float max_motor_torque; ///< 最大马达力 [N] float motor_speed; ///< 马达转速 [degree/s] float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固 float damping_ratio; ///< 弹簧阻尼率,值越大关节运动阻尼越大 Param(Body* body_a, Body* body_b, Point const& anchor, Vec2 const& axis, float frequency_hz = 2.0f, float damping_ratio = 0.7f, bool enable_motor = false, float max_motor_torque = 0.0f, float motor_speed = 0.0f) : ParamBase(body_a, body_b) , anchor(anchor) , axis(axis) , enable_motor(enable_motor) , max_motor_torque(max_motor_torque) , motor_speed(motor_speed) , frequency_hz(frequency_hz) , damping_ratio(damping_ratio) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, Vec2 const& axis, float frequency_hz = 2.0f, float damping_ratio = 0.7f, bool enable_motor = false, float max_motor_torque = 0.0f, float motor_speed = 0.0f) : Param(body_a.get(), body_b.get(), anchor, axis, frequency_hz, damping_ratio, enable_motor, max_motor_torque, motor_speed) { } }; /// \~chinese /// @brief 创建轮关节 /// @param world 物理世界 /// @param param 关节参数 static WheelJointPtr Create(World* world, Param const& param); WheelJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 获取关节当前的平移距离 float GetJointTranslation() const; /// \~chinese /// @brief 获取关节当前的线性速度 float GetJointLinearSpeed() const; /// \~chinese /// @brief 获取关节当前的角度 float GetJointAngle() const; /// \~chinese /// @brief 获取关节当前的旋转速度 float GetJointAngularSpeed() const; /// \~chinese /// @brief 是否启用马达 bool IsMotorEnabled() const; /// \~chinese /// @brief 设置是否启用马达 void EnableMotor(bool flag); /// \~chinese /// @brief 设置马达转速 [degree/s] void SetMotorSpeed(float speed); /// \~chinese /// @brief 获取马达转速 [degree/s] float GetMotorSpeed() const; /// \~chinese /// @brief 设置最大马达转矩 [N/m] void SetMaxMotorTorque(float torque); /// \~chinese /// @brief 获取最大马达转矩 [N/m] float GetMaxMotorTorque() const; /// \~chinese /// @brief 设置弹簧响应速度 void SetSpringFrequencyHz(float hz); /// \~chinese /// @brief 获取弹簧响应速度 float GetSpringFrequencyHz() const; /// \~chinese /// @brief 设置弹簧阻尼率 void SetSpringDampingRatio(float ratio); /// \~chinese /// @brief 获取弹簧阻尼率 float GetSpringDampingRatio() const; private: b2WheelJoint* raw_joint_; }; /// \~chinese /// @brief 鼠标关节 /// @details 用于使身体的某个点追踪世界上的指定点,例如让物体追踪鼠标位置 class KGE_API MouseJoint : public Joint { public: /// \~chinese /// @brief 鼠标关节参数 struct Param : public Joint::ParamBase { Point target; ///< 关节作用目标位置 float max_force; ///< 作用在物体A上的最大力 float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固 float damping_ratio; ///< 阻尼率,值越大关节运动阻尼越大 Param(Body* body_a, Body* body_b, Point const& target, float max_force, float frequency_hz = 5.0f, float damping_ratio = 0.7f) : ParamBase(body_a, body_b) , target(target) , max_force(max_force) , frequency_hz(frequency_hz) , damping_ratio(damping_ratio) { } Param(BodyPtr body_a, BodyPtr body_b, Point const& target, float max_force, float frequency_hz = 5.0f, float damping_ratio = 0.7f) : Param(body_a.get(), body_b.get(), target, max_force, frequency_hz, damping_ratio) { } }; /// \~chinese /// @brief 创建鼠标关节 /// @param world 物理世界 /// @param param 关节参数 static MouseJointPtr Create(World* world, Param const& param); MouseJoint(); /// \~chinese /// @brief 初始化关节 bool InitJoint(World* world, Param const& param); /// \~chinese /// @brief 设定最大摩擦力 [N] void SetMaxForce(float force); /// \~chinese /// @brief 获取最大摩擦力 [N] float GetMaxForce() const; /// \~chinese /// @brief 设置响应速度 [hz] void SetFrequency(float hz); /// \~chinese /// @brief 获取响应速度 [hz] float GetFrequency() const; /// \~chinese /// @brief 设置阻尼率 void SetDampingRatio(float ratio); /// \~chinese /// @brief 获取阻尼率 float GetDampingRatio() const; private: b2MouseJoint* raw_joint_; }; /** @} */ inline b2Joint* Joint::GetB2Joint() const { return joint_; } inline World* Joint::GetWorld() const { return world_; } inline void DistanceJoint::SetFrequency(float hz) { KGE_ASSERT(raw_joint_); raw_joint_->SetFrequency(hz); } inline float DistanceJoint::GetFrequency() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetFrequency(); } inline void DistanceJoint::SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); } inline float DistanceJoint::GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); } inline float PrismaticJoint::GetReferenceAngle() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetReferenceAngle()); } inline bool PrismaticJoint::IsLimitEnabled() const { KGE_ASSERT(raw_joint_); return raw_joint_->IsLimitEnabled(); } inline void PrismaticJoint::EnableLimit(bool flag) { KGE_ASSERT(raw_joint_); raw_joint_->EnableLimit(flag); } inline bool PrismaticJoint::IsMotorEnabled() const { KGE_ASSERT(raw_joint_); return raw_joint_->IsMotorEnabled(); } inline void PrismaticJoint::EnableMotor(bool flag) { KGE_ASSERT(raw_joint_); raw_joint_->EnableMotor(flag); } inline void PrismaticJoint::SetMotorSpeed(float speed) { KGE_ASSERT(raw_joint_); raw_joint_->SetMotorSpeed(math::Degree2Radian(speed)); } inline float PrismaticJoint::GetMotorSpeed() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetMotorSpeed()); } inline void PrismaticJoint::SetMaxMotorForce(float force) { KGE_ASSERT(raw_joint_); raw_joint_->SetMaxMotorForce(force); } inline float PrismaticJoint::GetMaxMotorForce() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetMaxMotorForce(); } inline float RevoluteJoint::GetReferenceAngle() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetReferenceAngle()); } inline bool RevoluteJoint::IsLimitEnabled() const { KGE_ASSERT(raw_joint_); return raw_joint_->IsLimitEnabled(); } inline void RevoluteJoint::EnableLimit(bool flag) { KGE_ASSERT(raw_joint_); raw_joint_->EnableLimit(flag); } inline bool RevoluteJoint::IsMotorEnabled() const { KGE_ASSERT(raw_joint_); return raw_joint_->IsMotorEnabled(); } inline void RevoluteJoint::EnableMotor(bool flag) { KGE_ASSERT(raw_joint_); raw_joint_->EnableMotor(flag); } inline void RevoluteJoint::SetMotorSpeed(float speed) { KGE_ASSERT(raw_joint_); raw_joint_->SetMotorSpeed(math::Degree2Radian(speed)); } inline float RevoluteJoint::GetMotorSpeed() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetMotorSpeed()); } inline float WeldJoint::GetReferenceAngle() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetReferenceAngle()); } inline void WeldJoint::SetFrequency(float hz) { KGE_ASSERT(raw_joint_); raw_joint_->SetFrequency(hz); } inline float WeldJoint::GetFrequency() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetFrequency(); } inline void WeldJoint::SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); } inline float WeldJoint::GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); } inline float WheelJoint::GetJointAngle() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetJointAngle()); } inline float WheelJoint::GetJointAngularSpeed() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetJointAngularSpeed()); } inline bool WheelJoint::IsMotorEnabled() const { KGE_ASSERT(raw_joint_); return raw_joint_->IsMotorEnabled(); } inline void WheelJoint::EnableMotor(bool flag) { KGE_ASSERT(raw_joint_); raw_joint_->EnableMotor(flag); } inline void WheelJoint::SetMotorSpeed(float speed) { KGE_ASSERT(raw_joint_); raw_joint_->SetMotorSpeed(math::Degree2Radian(speed)); } inline float WheelJoint::GetMotorSpeed() const { KGE_ASSERT(raw_joint_); return math::Radian2Degree(raw_joint_->GetMotorSpeed()); } inline void WheelJoint::SetSpringFrequencyHz(float hz) { KGE_ASSERT(raw_joint_); raw_joint_->SetSpringFrequencyHz(hz); } inline float WheelJoint::GetSpringFrequencyHz() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetSpringFrequencyHz(); } inline void WheelJoint::SetSpringDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetSpringDampingRatio(ratio); } inline float WheelJoint::GetSpringDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetSpringDampingRatio(); } inline void MouseJoint::SetFrequency(float hz) { KGE_ASSERT(raw_joint_); raw_joint_->SetFrequency(hz); } inline float MouseJoint::GetFrequency() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetFrequency(); } inline void MouseJoint::SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); } inline float MouseJoint::GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); } } // namespace physics } // namespace kiwano