Unfortunately a project where the code is intertwined with many things (in this instance the Babylon sketch is abstracted into SvelteJS components).
However … I worked it out!
Some general things that helped were:
- transforming my worldspace ball and socket coordinates with the world matrix of the mesh its being applied to
- only getting these mesh world matrixes at initialisation (since this will change between frames)
- cloning points just in case
Here is an extract (apologies I can’t share full sketch):
let nodeA = new BB.Vector3(0,1,0)
let nodeB = new BB.Vector3(-1,0.2,0)
let outerA1 = new BB.Vector3(-1,0.2,0)
let outerA2 = new BB.Vector3(1,2,1)
let outerA3 = new BB.Vector3(-1,2,1)
let lineA = null // becomes a cylinder mesh between nodeA and outerA1 (and nodeB)
let lineB = null // becomes a cylinder mesh between nodeA and outerA2
let lineC = null // becomes a cylinder mesh between nodeA and outerA3
let nodeSphereA = null // becomes sphere mesh at point nodeA
let nodeSphereB = null // becomes sphere mesh at point nodeB
let physics, scene, ground
let lineMatrixA = null // SET THESE ONCE (just in case - YES ✅)
let lineMatrixB = null // SET THESE ONCE (just in case - YES ✅)
let lineMatrixC = null // SET THESE ONCE (just in case - YES ✅)
function createTripleSocket( mesh ) {
const aggre = new BB.PhysicsAggregate( mesh, BB.PhysicsShapeType.SPHERE, {
mass: settings.ballMass,
}, scene )
// EDGES DON'T COLLIDE (IMPORTANT)
aggre.shape.filterCollideMask = 1
aggre.shape.filterMembershipMask = 2
const centerPivot = new BB.Vector3(0,0,0)
lineMatrixA = lineA.getWorldMatrix().invert()
lineMatrixB = lineB.getWorldMatrix().invert()
lineMatrixC = lineC.getWorldMatrix().invert()
// GET NODE A POSITION FROM CYLINDER COORDINATES
const connectedPivotA = BB.Vector3.TransformCoordinates(nodeA.clone(), lineMatrixA)
const connectedPivotB = BB.Vector3.TransformCoordinates(nodeA.clone(), lineMatrixB)
const connectedPivotC = BB.Vector3.TransformCoordinates(nodeA.clone(), lineMatrixC)
// CREATE BALL AND SOCKETS
const axisA = new BB.Vector3(1, 1, 1)
const axisB = new BB.Vector3(1, 1, 1)
const jointA = new BB.BallAndSocketConstraint(
centerPivot,
connectedPivotA,
axisA,
axisB,
scene
)
const jointB = new BB.BallAndSocketConstraint(
centerPivot,
connectedPivotB,
axisA,
axisB,
scene
)
const jointC = new BB.BallAndSocketConstraint(
centerPivot,
connectedPivotC,
axisA,
axisB,
scene
)
mesh.physicsBody.addConstraint(lineA.physicsBody, jointA)
mesh.physicsBody.addConstraint(lineB.physicsBody, jointB)
mesh.physicsBody.addConstraint(lineC.physicsBody, jointC)
addDragBehaviour( mesh )
}
function createNextSocket(mesh) {
const aggre = new BB.PhysicsAggregate( mesh, BB.PhysicsShapeType.SPHERE, {
mass: settings.ballMass,
}, scene )
// EDGES DON'T COLLIDE (IMPORTANT)
aggre.shape.filterCollideMask = 1
aggre.shape.filterMembershipMask = 2
const centerPivot = new BB.Vector3(0,0,0)
// GET NODE A POSITION FROM CYLINDER COORDINATES
let POINT = outerA1.clone()
const connectedPivotA = BB.Vector3.TransformCoordinates(POINT, lineMatrixA) // HELP!
const axisA = new BB.Vector3(1, 1, 1)
const axisB = new BB.Vector3(1, 1, 1)
const jointA = new BB.BallAndSocketConstraint(
centerPivot,
connectedPivotA, // HELP!
axisA,
axisB,
scene
)
mesh.physicsBody.addConstraint(lineA.physicsBody, jointA)
addDragBehaviour( mesh )
}