Rapier ImpulseJoint Motors
Video Lecture
Description
In this lesson we will,
- Implement a follow cam to chase the car,
- Setup revolute ImpulseJoint constraints to join the front wheels to steering axels, and then to the car body,
- Use
configureMotorVelocity
to rotate the rear wheels of the car, - Use
configureMotorPosition
to steer the front wheels. - Use collision/interaction groups.
Impulsejoint
We are using the revolute type of ImpulseJoint
,
world.createImpulseJoint(RAPIER.JointData.revolute(...
The revolute joint prevents any relative movement between two rigid-bodies, except for relative rotations along one axis.
Types of ImpulseJoints
we can use in Rapier v0.12.0
,
Type | Description |
---|---|
Revolute |
Removes all degrees of freedom between the affected bodies except for the rotation along one axis. |
Fixed |
Removes all relative degrees of freedom between the affected bodies. Good for hard locking bodies together. |
Prismatic |
Removes all degrees of freedom between the affected bodies except for the translation along one axis. |
Spherical |
Removes all relative linear degrees of freedom between the affected bodies. |
Note that when spawning rigid bodies linked with joints, it is important to position the joint relative to the parent body, otherwise the physics engine will need to apply an opposite force to correct its position for the joint.
For example, the steering axels are added to the car body, but translated forward left and forward right, so they are positioned where you would expect the front wheels to be. When adding the front wheels to the axels, they can be joined at 0,0,0
, since the axels themselves have already been offset the car bodies centre.
It is also important that when shapes are added to the world, that they aren't positioned the same place as any existing shapes. This will cause unpredictable collisions and the body will appear to jump, spin or be thrown in some random way. The only time you can position a shape, in the same place as any other shape, is if you have set its collision group to ignore the other shape.
Joint motors
Impulse joints can be controlled using the configureMotorVelocity
and configureMotorPosition
methods.
In this example, configureMotorVelocity
controls continuous rotations for the rear wheels.
;(this.wheelBLMotor as RAPIER.PrismaticImpulseJoint).configureMotorVelocity(targetVelocity, factor)
The configureMotorPosition
controls how far left and right the steering moves.
;(this.wheelFLAxel as RAPIER.PrismaticImpulseJoint).configureMotorPosition(targetSteer, stiffness, damping)
The configureMotorPosition
method limits the amount of rotation, so that it doesn't continue to revolve like the configureMotorVelocity
method. However, If using the configureMotorPosition
method, you should also configure your ImpulseJoint
MotorModel
, to use the ForceBased
model. The default MotorModel
= AccelerationBased
, which is useful if calling the configureMotorVelocity
method.
;(this.wheelFRAxel as RAPIER.PrismaticImpulseJoint).configureMotorModel(RAPIER.MotorModel.ForceBased)
Rapier Collision Group Calculator
This example also demonstrates setting collision/interaction groups between each rigid body.
Without the collision group settings, the wheels and steering axels conflict with the car body and shake unpredictably.
So, each shape is added to its own membership group, and then a filter is applied.
If the group memberships are,
floor = 0
car = 1
wheel = 2
axel = 3
Then, the collision group calculations are,
-
The floor collides with the wheels and car.
membership=0, filter=[1,2]
=65542
-
The car collides with the floor only.
membership=1, filter=[0]
=131073
-
The wheels collide with the floor only.
membership=2, filter=[0]
=262145
-
The axels collide with nothing.
membership=3
=589823
Use collision groups to limit which shapes/colliders can collide with each other.
- Membership : A number or array. E.g.,
0
or1
or[0,2,3]
- Filter : A number, array or nothing. E.g.,
0
or1
or[0,2,3]
With the calculated value, when creating a rigid body, you can set the collision group.
const someShape = RAPIER.ColliderDesc.cuboid().setCollisionGroups(65542)
Lesson Scripts
./index.html
1 2 3 4 5 6 7 8 9 10 11 12 |
|
./src/style.css
1 2 3 4 |
|
./src/Box.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
./src/Car.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
|
./src/RapierDebugRenderer.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
./src/main.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
|