admin管理员组文章数量:1355540
I am trying to 'freeze objects together' using Bullet (via JavaScript + Three.JS + Ammo.js)
Here is my scene
Here we see a Merry-go-round simulation, in which 8 horses are generated above a turntable/disc.
This GIF illustrates the system working as expected - the 8 horses (instances of bodyA
) are frozen-in-place to the turntable/disc (bodyB
)
Each bodyA
(horse) has a bTFixedConstraint with bodyB
(disc). The problem becomes apparent when the disc (bodyB
) has different rotation applied: the horses are being rotated by a factor of bodyB
's rotation, knocking them off of their 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.
I have tried every combination of absolute and relative rotations that I can think of (to the point of making an interface to trial different combinations), but the horses never adhere correctly to the turntable.
Here's a simplified version of my btFixedConstraint
implementation
// bodyA = the rigidBody being attached
// bodyB = what bodyA is being attached to
const applyFixedConstraint = (bodyA, bodyB) => {
const relRotationAB = getRelativeRotation(bodyA, bodyB);
const relPosBA = getRelativePosition(bodyB, bodyA);
// FRAME IN A
const frameInA = new Ammo.btTransform();
frameInA.setIdentity();
frameInA.getOrigin().setValue(0, 0, 0);
frameInA.setRotation(new Ammo.btQuaternion(0,0,0,1)); // i.e. 'none'
// FRAME IN B
const frameInB = new Ammo.btTransform();
frameInB.setIdentity();
frameInB.getOrigin().setValue(relPosBA.x, relPosBA.y, relPosBA.z);
frameInB.setRotation(new Ammo.btQuaternion(relRotationAB.x, relRotationAB.y, relRotationAB.z, relRotationAB.w));
// 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
Since the bodyA/bodyB are unlikely to be causing an issue, 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 using btFixedConstraint
?
I am trying to 'freeze objects together' using Bullet (via JavaScript + Three.JS + Ammo.js)
Here is my scene https://codepen.io/PartyPants2/pen/emYLRPX?editors=0010
Here we see a Merry-go-round simulation, in which 8 horses are generated above a turntable/disc.
This GIF illustrates the system working as expected - the 8 horses (instances of bodyA
) are frozen-in-place to the turntable/disc (bodyB
)
Each bodyA
(horse) has a bTFixedConstraint with bodyB
(disc). The problem becomes apparent when the disc (bodyB
) has different rotation applied: the horses are being rotated by a factor of bodyB
's rotation, knocking them off of their 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.
I have tried every combination of absolute and relative rotations that I can think of (to the point of making an interface to trial different combinations), but the horses never adhere correctly to the turntable.
Here's a simplified version of my btFixedConstraint
implementation
// bodyA = the rigidBody being attached
// bodyB = what bodyA is being attached to
const applyFixedConstraint = (bodyA, bodyB) => {
const relRotationAB = getRelativeRotation(bodyA, bodyB);
const relPosBA = getRelativePosition(bodyB, bodyA);
// FRAME IN A
const frameInA = new Ammo.btTransform();
frameInA.setIdentity();
frameInA.getOrigin().setValue(0, 0, 0);
frameInA.setRotation(new Ammo.btQuaternion(0,0,0,1)); // i.e. 'none'
// FRAME IN B
const frameInB = new Ammo.btTransform();
frameInB.setIdentity();
frameInB.getOrigin().setValue(relPosBA.x, relPosBA.y, relPosBA.z);
frameInB.setRotation(new Ammo.btQuaternion(relRotationAB.x, relRotationAB.y, relRotationAB.z, relRotationAB.w));
// 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
Since the bodyA/bodyB are unlikely to be causing an issue, 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 using btFixedConstraint
?
1 Answer
Reset to default 0Update: further testing indicates moving BodyB after starting the simulation disrupts the axis of BodyA, so I'm likely incorrect after all. I am leaving this answer here until I can revise it as it may help someone else, it certainly would have helped me...
Well this took an unexpected turn. Hopefully it helps someone else out there.
BEHOLD! It is working: https://codepen.io/PartyPants2/pen/KwKrdvq
If you are as misfortunate as me and got stuck on this for literally a whole week, then I'm afraid I have some more bad news: this solution is so confounding that it will only raise further questions about the inner workings of Bullet/Ammo, and I do not have answers for you. And I never will.
All I know is this:
let motionStateB = bodyB.getMotionState();
const transformB = new Ammo.btTransform();
motionStateB.getWorldTransform(transformB);
console.log("Before", rotationA.x(), rotationA.y(), rotationA.z(),
rotationA.w())
// Before 0 0.9238795638084412 0 -0.3826834559440613
const rotationB = transformB.getRotation();
console.log("After", rotationA.x(), rotationA.y(), rotationA.z(),
rotationA.w());
// After 0 0 0 1
// Yes, seriously. It deleted rotationA's values for no reason.
// I don't even think this is rotationB's values. It's just... gone??
For some HORRIBLE reason, if you transformB.getRotation()
it DELETES the values of rotationA
.
Now that you know you have incorrect input values for absolutely no reason, we can now simply pre-store those quaternions and use them in the final transforms, making the solution to the question simply:
The correctframeInA
rotation isbodyA
's rotation.- The correct
frameInB
rotation isbodyB
's rotation.
Update: nevermind, this is probably wrong. read top
(Just make sure you are getting real values for those quaternions, Ammo likes to obliterate unrelated memory references for some reason I will never understand)
See CodePen for proof
本文标签:
版权声明:本文标题:javascript - btFixedConstraint freeze objects - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743962159a2569227.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论