UPDATED
I am trying to 'freeze objects together' using Bullet (via Ammo.js, using Three.js as the renderer)
Here is my scene https://codepen.io/PartyPants2/pen/KwKrdvq?editors=0010
The scene is a Merry-go-round simulation, in which 8 horses are generated above a turntable/disc
This GIF resembles the system working as expected - the horses appear 'pinned in space' to the turntable/disc.
All is well until we apply a different initial rotation to the turntable. The horses are now disorientated by a factor of the turntable's rotation, see below
(The presence of a second axis indicates we are misaligned from the target axis)
When the physics starts, it causes the FixedConstraints to activate. Because the FixedConstraints are not configured correctly, it causes the horses to lose alignment with their target axis, below
One would assume by looking at this that a relative rotation should be implemented... and I have done exactly that. In fact here is a list (below) of rotations we could give to bodyA or bodyB (that I can think of) as well as making an interface to trial different combinations (above)
"unset" // don't give any value
"eulerXYZ 0,0,90" // EulerXYZ(0,0,90)
"quat 0,0,0,1" // A default quaternion (0,0,0,1)
"A*" // The absolute rotation of bodyA (via Three.js)
"B*" // The absolute rotation of bodyB (via Three.js)
"A-to-B" // The relative rotation of bodyA to BodyB (via Ammo.js)
"A-to-B*" // The relative rotation of bodyA to BodyB (via Three.js)
"B-to-A" // The relative rotation of bodyB to BodyA (via Ammo.js)
"B-to-A*" // The relative rotation of bodyB to BodyA (via Three.js)
Despite my efforts, it doesn't seem like any combination of rotation/position pairs results in successfully freezing the bodies together in space. I am open to suggestions on ones I have not considered!
Here's a simplified version of my btFixedConstraint
implementation
const freeze = (bodyA, bodyB) => {
const relRotationBtoA = getRelativeRotation(bodyA, bodyB);
const relPositionBtoA = getRelativePosition(bodyA, bodyB);
// FRAME IN A
const frameInA = new Ammo.btTransform();
frameInA.setIdentity();
frameInA.getOrigin().setValue(0, 0, 0); // i.e. "0,0,0"
frameInA.setRotation(new Ammo.btQuaternion(0,0,0,1)); // i.e. "quat 0,0,0,1"
// FRAME IN B
const frameInB = new Ammo.btTransform();
frameInB.setIdentity();
frameInB.getOrigin().setValue(relPositionBtoA.x, relPositionBtoA.y, relPositionBtoA.z); // i.e. "A-to-B*"
frameInB.setRotation(new Ammo.btQuaternion(relRotationBtoA.x, relRotationBtoA.y, relRotationBtoA.z, relRotationBtoA.w)); // i.e. "A-to-B*"
// RESULT
const fixedConstraint = new Ammo.btFixedConstraint(bodyA,bodyB,frameInA,frameInB); // this line doesn't "freeze items in the air" like it should
physicsWorld.addConstraint(fixedConstraint, true);
return fixedConstraint;
}
Objects in Bullet/Ammo.js typically have a variety of different constructor patterns but btFixedConstraint only just one: bodyA,bodyB,frameInA,frameInB
, thus the solution MUST BE to fix the frameInA
or frameInB
parameters.
That said, how can I calculate the correct btTransform's (frameInA
and frameInB
) for freezing bodies together (relative to their initial rotations and positions in space) using btFixedConstraint
?
It turns out the code was perfect, but the library must've had some bugs. Using an updated build of ammo.js, compiled by reganio, everything works fine, with the following options:
{
// ....
frameInA_position: "unset",
frameInA_rotation: "unset",
frameInB_position: "A-to-B*",
frameInB_rotation: "A-to-B*"
}
or
{
// ....
frameInA_position: "B-to-A*",
frameInA_rotation: "B-to-A*",
frameInB_position: "unset",
frameInB_rotation: "unset"
}
Here's a codesanbox with the original code and the newer version of ammo.js.