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 | |
8 | using namespace physx; |
9 | |
10 | namespace 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 | } |