1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "BsPhysXHingeJoint.h"
4#include "BsFPhysXJoint.h"
5#include "BsPhysXRigidbody.h"
6#include "PxRigidDynamic.h"
7
8using namespace physx;
9
10namespace bs
11{
12 PxRevoluteJointFlag::Enum toPxFlag(HingeJointFlag flag)
13 {
14 switch (flag)
15 {
16 case HingeJointFlag::Limit:
17 return PxRevoluteJointFlag::eLIMIT_ENABLED;
18 default:
19 case HingeJointFlag::Drive:
20 return PxRevoluteJointFlag::eDRIVE_ENABLED;
21 }
22 }
23
24 PhysXHingeJoint::PhysXHingeJoint(PxPhysics* physx, const HINGE_JOINT_DESC& desc)
25 :HingeJoint(desc)
26 {
27 PxRigidActor* actor0 = nullptr;
28 if (desc.bodies[0].body != nullptr)
29 actor0 = static_cast<PhysXRigidbody*>(desc.bodies[0].body)->_getInternal();
30
31 PxRigidActor* actor1 = nullptr;
32 if (desc.bodies[1].body != nullptr)
33 actor1 = static_cast<PhysXRigidbody*>(desc.bodies[1].body)->_getInternal();
34
35 PxTransform tfrm0 = toPxTransform(desc.bodies[0].position, desc.bodies[0].rotation);
36 PxTransform tfrm1 = toPxTransform(desc.bodies[1].position, desc.bodies[1].rotation);
37
38 PxRevoluteJoint* joint = PxRevoluteJointCreate(*physx, actor0, tfrm0, actor1, tfrm1);
39 joint->userData = this;
40
41 mInternal = bs_new<FPhysXJoint>(joint, desc);
42
43 PxRevoluteJointFlags flags;
44
45 if (((UINT32)desc.flag & (UINT32)HingeJointFlag::Limit) != 0)
46 flags |= PxRevoluteJointFlag::eLIMIT_ENABLED;
47
48 if (((UINT32)desc.flag & (UINT32)HingeJointFlag::Drive) != 0)
49 flags |= PxRevoluteJointFlag::eDRIVE_ENABLED;
50
51 joint->setRevoluteJointFlags(flags);
52
53 // Must be set after global flags, as it will append to them.
54 // Calls to virtual methods are okay here.
55 setLimit(desc.limit);
56 setDrive(desc.drive);
57 }
58
59 PhysXHingeJoint::~PhysXHingeJoint()
60 {
61 bs_delete(mInternal);
62 }
63
64 Radian PhysXHingeJoint::getAngle() const
65 {
66 return Radian(getInternal()->getAngle());
67 }
68
69 float PhysXHingeJoint::getSpeed() const
70 {
71 return getInternal()->getVelocity();
72 }
73
74 LimitAngularRange PhysXHingeJoint::getLimit() const
75 {
76 PxJointAngularLimitPair pxLimit = getInternal()->getLimit();
77
78 LimitAngularRange limit;
79 limit.lower = pxLimit.lower;
80 limit.upper = pxLimit.upper;
81 limit.contactDist = pxLimit.contactDistance;
82 limit.restitution = pxLimit.restitution;
83 limit.spring.stiffness = pxLimit.stiffness;
84 limit.spring.damping = pxLimit.damping;
85
86 return limit;
87 }
88
89 void PhysXHingeJoint::setLimit(const LimitAngularRange& limit)
90 {
91 PxJointAngularLimitPair pxLimit(limit.lower.valueRadians(), limit.upper.valueRadians(), limit.contactDist);
92 pxLimit.stiffness = limit.spring.stiffness;
93 pxLimit.damping = limit.spring.damping;
94 pxLimit.restitution = limit.restitution;
95
96 getInternal()->setLimit(pxLimit);
97 }
98
99 HingeJointDrive PhysXHingeJoint::getDrive() const
100 {
101 HingeJointDrive drive;
102 drive.speed = getInternal()->getDriveVelocity();
103 drive.forceLimit = getInternal()->getDriveForceLimit();
104 drive.gearRatio = getInternal()->getDriveGearRatio();
105 drive.freeSpin = getInternal()->getRevoluteJointFlags() & PxRevoluteJointFlag::eDRIVE_FREESPIN;
106
107 return drive;
108 }
109
110 void PhysXHingeJoint::setDrive(const HingeJointDrive& drive)
111 {
112 getInternal()->setDriveVelocity(drive.speed);
113 getInternal()->setDriveForceLimit(drive.forceLimit);
114 getInternal()->setDriveGearRatio(drive.gearRatio);
115 getInternal()->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_FREESPIN, drive.freeSpin);
116 }
117
118 void PhysXHingeJoint::setFlag(HingeJointFlag flag, bool enabled)
119 {
120 getInternal()->setRevoluteJointFlag(toPxFlag(flag), enabled);
121 }
122
123 bool PhysXHingeJoint::hasFlag(HingeJointFlag flag) const
124 {
125 return getInternal()->getRevoluteJointFlags() & toPxFlag(flag);
126 }
127
128 PxRevoluteJoint* PhysXHingeJoint::getInternal() const
129 {
130 FPhysXJoint* internal = static_cast<FPhysXJoint*>(mInternal);
131
132 return static_cast<PxRevoluteJoint*>(internal->_getInternal());
133 }
134}