Skip to content

Commit e58d387

Browse files
willeastcottclaude
andcommitted
refactor(joint): derive motor engagement from maxMotorForce
Remove the redundant enableMotor boolean. A motor with a zero force budget does nothing, so a positive maxMotorForce is the natural "motor active" signal - mirroring how a spring acts when its stiffness is positive. This drops another boolean from the public surface and removes a redundant state without losing expressiveness: free (zero force), drive (positive force, non-zero speed) and brake/hold (positive force, zero speed) all remain reachable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent c389d97 commit e58d387

4 files changed

Lines changed: 14 additions & 42 deletions

File tree

examples/src/examples/physics/joints.example.mjs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ createJoint('windmill-hinge', new pc.Vec3(-5.5, 4, 0.3), new pc.Vec3(0, -90, 0),
177177
type: pc.JOINTTYPE_HINGE,
178178
entityA: rotor,
179179
entityB: pole,
180-
enableMotor: true,
181180
motorSpeed: 90,
182181
maxMotorForce: 100
183182
});
@@ -221,13 +220,12 @@ app.root.addChild(rail);
221220
const platform = createBox('platform', new pc.Vec3(0.8, 0.25, 0.6), new pc.Vec3(1.5, 0.85, 0), green, 'dynamic', 10);
222221

223222
// the slider is pinned to the world (entityB is null) - the platform can only translate along
224-
// the joint's X axis, driven back and forth by the motor
223+
// the joint's X axis, driven back and forth by the motor (active because maxMotorForce > 0)
225224
const sliderJoint = createJoint('slider', new pc.Vec3(1.5, 0.85, 0), new pc.Vec3(0, 0, 0), {
226225
type: pc.JOINTTYPE_SLIDER,
227226
entityA: platform,
228227
enableLimits: true,
229228
limits: new pc.Vec2(-2, 2),
230-
enableMotor: true,
231229
motorSpeed: 1.5,
232230
maxMotorForce: 400
233231
});

src/framework/components/joint/component.js

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ const hingeJoint = {
128128
// bullet's hinge motor clamp is an impulse per simulation step, so scale the torque by
129129
// the fixed timestep
130130
const maxImpulse = joint.maxMotorForce * joint.system.app.systems.rigidbody.fixedTimeStep;
131-
joint._constraint.enableAngularMotor(joint.enableMotor, joint.motorSpeed * math.DEG_TO_RAD, maxImpulse);
131+
joint._constraint.enableAngularMotor(joint.maxMotorForce > 0, joint.motorSpeed * math.DEG_TO_RAD, maxImpulse);
132132
}
133133
};
134134

@@ -157,7 +157,7 @@ const sliderJoint = {
157157

158158
updateMotor(joint) {
159159
const constraint = joint._constraint;
160-
constraint.setPoweredLinMotor(joint.enableMotor);
160+
constraint.setPoweredLinMotor(joint.maxMotorForce > 0);
161161
constraint.setTargetLinMotorVelocity(joint.motorSpeed);
162162
constraint.setMaxLinMotorForce(joint.maxMotorForce);
163163
}
@@ -352,9 +352,6 @@ class JointComponent extends Component {
352352
/** @private */
353353
_limits = new Vec2(-45, 45);
354354

355-
/** @private */
356-
_enableMotor = false;
357-
358355
/** @private */
359356
_motorSpeed = 0;
360357

@@ -680,32 +677,11 @@ class JointComponent extends Component {
680677
}
681678

682679
/**
683-
* Sets whether the joint's motor is enabled. The motor drives a hinge joint's rotation or a
684-
* slider joint's translation towards {@link motorSpeed}, applying up to
685-
* {@link maxMotorForce}. Not used by other joint types. Defaults to false.
686-
*
687-
* @type {boolean}
688-
*/
689-
set enableMotor(arg) {
690-
if (this._enableMotor !== arg) {
691-
this._enableMotor = arg;
692-
this._updateMotor();
693-
}
694-
}
695-
696-
/**
697-
* Gets whether the joint's motor is enabled.
698-
*
699-
* @type {boolean}
700-
*/
701-
get enableMotor() {
702-
return this._enableMotor;
703-
}
704-
705-
/**
706-
* Sets the target speed of the joint's motor. For hinge joints, this is an angular speed in
707-
* degrees per second. For slider joints, this is a linear speed in meters per second. Only
708-
* used when {@link enableMotor} is true. Defaults to 0.
680+
* Sets the target speed the motor drives towards. For hinge joints, this is an angular speed
681+
* in degrees per second; for slider joints, a linear speed in meters per second. The motor is
682+
* active only while {@link maxMotorForce} is greater than 0; with a target speed of 0 and a
683+
* positive force the motor acts as a brake, holding the joint at rest. Only used by hinge and
684+
* slider joints. Defaults to 0.
709685
*
710686
* @type {number}
711687
*/
@@ -717,7 +693,7 @@ class JointComponent extends Component {
717693
}
718694

719695
/**
720-
* Gets the target speed of the joint's motor.
696+
* Gets the target speed the motor drives towards.
721697
*
722698
* @type {number}
723699
*/
@@ -726,9 +702,10 @@ class JointComponent extends Component {
726702
}
727703

728704
/**
729-
* Sets the maximum force the joint's motor can apply to reach {@link motorSpeed}. For hinge
730-
* joints, this is a torque in Newton meters. For slider joints, this is a force in Newtons.
731-
* Only used when {@link enableMotor} is true. Defaults to 0.
705+
* Sets the maximum force the motor can apply to reach {@link motorSpeed}. For hinge joints,
706+
* this is a torque in Newton meters; for slider joints, a force in Newtons. The motor is
707+
* disabled while this is 0, so set it greater than 0 to engage the motor. Only used by hinge
708+
* and slider joints. Defaults to 0.
732709
*
733710
* @type {number}
734711
*/

src/framework/components/joint/system.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { JointComponent } from './component.js';
88
const _properties = [
99
'type',
1010
'enableCollision', 'breakImpulse',
11-
'enableLimits', 'limits', 'enableMotor', 'motorSpeed', 'maxMotorForce',
11+
'enableLimits', 'limits', 'motorSpeed', 'maxMotorForce',
1212
'swingLimitY', 'swingLimitZ', 'twistLimit',
1313
'linearMotionX', 'linearMotionY', 'linearMotionZ',
1414
'linearLimitsX', 'linearLimitsY', 'linearLimitsZ',

test/framework/components/joint/component.test.mjs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ describe('JointComponent', function () {
3939
breakImpulse: 500,
4040
enableLimits: true,
4141
limits: new Vec2(-10, 80),
42-
enableMotor: true,
4342
motorSpeed: 90,
4443
maxMotorForce: 12,
4544
swingLimitY: 30,
@@ -75,7 +74,6 @@ describe('JointComponent', function () {
7574
expect(c.breakImpulse).to.equal(500);
7675
expect(c.enableLimits).to.equal(true);
7776
expect(c.limits.equals(new Vec2(-10, 80))).to.equal(true);
78-
expect(c.enableMotor).to.equal(true);
7977
expect(c.motorSpeed).to.equal(90);
8078
expect(c.maxMotorForce).to.equal(12);
8179
expect(c.swingLimitY).to.equal(30);
@@ -119,7 +117,6 @@ describe('JointComponent', function () {
119117
expect(c.isBroken).to.equal(false);
120118
expect(c.enableLimits).to.equal(false);
121119
expect(c.limits.equals(new Vec2(-45, 45))).to.equal(true);
122-
expect(c.enableMotor).to.equal(false);
123120
expect(c.motorSpeed).to.equal(0);
124121
expect(c.maxMotorForce).to.equal(0);
125122
expect(c.swingLimitY).to.equal(45);

0 commit comments

Comments
 (0)