-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a physics joint component #2095
Conversation
Not sure if you were looking for feedback here or on the forum post but a few points.
|
Many constraint configurations can have only single body defined, that way constraint will be between world and body. Also (for example), constraint entity, might have a spring model related to it, and it will be undesirable for that entity to be a child of one of related bodies.
+1. I think best would be if Engine as well as Editor would provide "type" for constraint, with more simple controls for simple ones, like ball joint, or hinge joint, and if developer needs - full on 6dof custom one. |
I think a separate entity per joint is probably best - it also may be clearer if a single rigid (or soft) body has many of joints/constraints? +1 for presets - and ability to create custom 6 DOF joint - and regarding limits when using a preset, you would want to make specifying limits as intuitive as possible for each type of preset - e.g for |
I've done some more work on this PR. I've added spring support for each linear/angular axis. It's pretty cool. See tweet: |
When looking over the introduced API with X, Y and Z, I felt exposing those as Vec3 would be nicer. And for the limits where the value is Vec2, I'd prefer Vec3 lower and Vec3 upper. It would also make the inspector more readable I think. |
I'd be also great to create a new issue for the follow up work, so that a good comments from this PR are considered for later - like the different ammo constrain types. |
const rot = new Quat(); | ||
rot.setFromMat4(pcTransform); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this avoid temporary allocation?
const ammoVec = new Ammo.btVector3(pos.x, pos.y, pos.z); | ||
const ammoQuat = new Ammo.btQuaternion(rot.x, rot.y, rot.z, rot.w); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even these could be static allocations on the class maybe
const aly = this._angularLimitsY; | ||
const alz = this._angularLimitsZ; | ||
|
||
const limits = new Ammo.btVector3(alx.x, aly.x, alz.x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid the allocation? few more times in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's surprisingly not easy to do that actually. Because Ammo may or may not be loaded. >99% of PlayCanvas apps will not even use the joint component, so doing any static allocations is perhaps more to be avoided here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approving with some comments and suggestions
Thanks for the review, @mvaligursky. So it's tricky. Because often, you just want to enable 1, or maybe 2, degrees of freedom. The current API lets you consider each DoF in turn. And imagine what the Editor UI would look like. For each DoF, there is a boolean to enable the spring. If that's unchecked (the default for each DoF), damping, stiffness, equilibrium can all be hidden. These properties need to be grouped together for each DoF if that's going to work well. |
Hey now that makes sense .. I didn't realize that. I take back my suggestion then. |
Some comments: Would using alternative naming help with understanding what each axis constrains? For example roll or twist for the Z axis and maybe pitch and yaw for Y and X axis. Also, although grouping limits into Vec2 in fine for the underlying implementation - expressing that the first value is the lower limit and second value is the upper limit could be useful in the naming in the API - or at least in the editor inspector? Also, maybe beyond the scope of this PR, what are the plans for in-editor visualization of joint setup? |
@raytranuk We don't use roll, pitch and yaw anywhere else in the API - and Bullet don't use those terms in their public API either. In the Editor, we can have labels For in-editor visualization, we will need a joint gizmo. Scary job, but yes, we'll need that at some point, once the runtime side is nailed down. |
It does make sense to stay consistent - so that knowledge gained from working with other places that use rotations in the engine will apply here - good tool tips in editor (and eventually good editor gizmos) will be helpful too.
It maybe worth considering exposing accessors for lower and upper limits to be set individually - if we feel users would find that useful - but it would mainly be a convenience.
Agree. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approving
Is this the recommended way of doing constraints today? I noticed it's not in the public API docs but is in the engine. Alternatively, there are the constraint scripts written here: https://playcanvas.com/project/618829/overview/physics-constraints For reference, I'm trying to build a ragdoll. |
It is not recommended currently. A joint must be destroyed before any of the attached rigidbodies are destroyed. At the moment rigidbody component does not consider, if there is a constraint attached to it on body destruction, which will crash Ammo. |
I have modified a fork of playcanvas [here] to implement multiple joint types using native bullet/ammo implementations (6DOF, spherical/cone-twist, hinge/revolute, slider/prismatic, and fixed). In addition, this version of playcanvas supports bullet multibody articulations. I do not have an example, though multibodies are supposed to be much more stable (than the current rigid bodies) for simulating articulations with many joints. |
Joint Component
This PR add support for physics joints (AKA constraints):
You can even enable spring 'motors' to power constraints:
Internally, it uses the ammo.js
btGeneric6DofSpringConstraint
class to implement a generic 6 degrees of freedom joint.API Overview
Here is the new API (it will be private initially until it has had further testing):
pc.JointComponent#angularDampingX
number
pc.JointComponent#angularDampingY
number
pc.JointComponent#angularDampingZ
number
pc.JointComponent#angularEquilibriumX
number
pc.JointComponent#angularEquilibriumY
number
pc.JointComponent#angularEquilibriumZ
number
pc.JointComponent#angularLimitsX
pc.Vec2
pc.JointComponent#angularLimitsY
pc.Vec2
pc.JointComponent#angularLimitsZ
pc.Vec2
pc.JointComponent#angularMotionX
string
"locked"
,"limited"
or"free"
. Defaults to"locked"
.pc.JointComponent#angularMotionY
string
"locked"
,"limited"
or"free"
. Defaults to"locked"
.pc.JointComponent#angularMotionZ
string
"locked"
,"limited"
or"free"
. Defaults to"locked"
.pc.JointComponent#angularSpringX
boolean
pc.JointComponent#angularSpringY
boolean
pc.JointComponent#angularSpringZ
boolean
pc.JointComponent#angularStiffnessX
number
pc.JointComponent#angularStiffnessY
number
pc.JointComponent#angularStiffnessZ
number
pc.JointComponent#breakForce
number
pc.JointComponent#enableCollision
boolean
pc.JointComponent#entityA
pc.Entity
pc.JointComponent#entityB
pc.Entity
pc.JointComponent#linearDampingX
number
pc.JointComponent#linearDampingY
number
pc.JointComponent#linearDampingZ
number
pc.JointComponent#linearEquilibriumX
number
pc.JointComponent#linearEquilibriumY
number
pc.JointComponent#linearEquilibriumZ
number
pc.JointComponent#linearLimitsX
pc.Vec2
pc.JointComponent#linearLimitsY
pc.Vec2
pc.JointComponent#linearLimitsZ
pc.Vec2
pc.JointComponent#linearMotionX
string
"locked"
,"limited"
or"free"
. Defaults to"locked"
.pc.JointComponent#linearMotionY
string
"locked"
,"limited"
or"free"
. Defaults to"locked"
.pc.JointComponent#linearMotionZ
string
"locked"
,"limited"
or"free"
. Defaults to"locked"
.pc.JointComponent#linearSpringX
boolean
pc.JointComponent#linearSpringY
boolean
pc.JointComponent#linearSpringZ
boolean
pc.JointComponent#linearStiffnessX
number
pc.JointComponent#linearStiffnessY
number
pc.JointComponent#linearStiffnessZ
number
Code Example:
Proposed Editor UI
The following is the proposed UI for the joint component in the Editor. It's prototyped below as a script component.
Note that the spring checkboxes should probably show/hide stiffness and equilibrium attributes of the corresponding DOF.
Open questions
At the moment, a joint component would live on its own entity, separate from
entityA
andentityB
. But should a joint component be added to the same entity asentityA
? This would mean theentityA
property would be implicit. One benefit of that is that you'd require one fewer entity, so your hierarchy would be simpler. But then a system for offsetting/editing the position/orientation of the joint would be needed.Should the joint expose presets for making it easier to configure simple, commonly needed joint types like a hinge?
Should this component leverage the other ammo.js constraint types for these presets like:
btPoint2PointConstraint
btHingeConstraint
btConeTwistConstraint
Or should everything be built using the
btGeneric6DofConstraint
API? Are the more specialized constraint types more stable and/or more performant? It would probably make the code bulkier to utilize the other ammo.js constraint classes.Should limits be in pairs (so 3
pc.Vec2
s for angular limits and 3 for linear)? Or should there be 2 `pc.Vec3's for lower and upper for angular and the same again for linear? Or should they be individual numbers? For now, I've made them pairs (one for each axis) because I think that's easier to visualize when configuring a joint.Fixes #478
I confirm I have signed the Contributor License Agreement.