# Basic use of V2 Havok physics joints (BallAndSocketConstraint)

Hello, I’m confused how to get even a basic implementation of a BallAndSocketConstraint working with Havok V2 physics.

I create two mesh cylinders between pointA and pointB, and between pointB and pointC (where pointB is where there should be a connection between two).

For the constructor for BallAndSocketConstraint, there are 4 arguments: pivotA, pivotB, axisA, axisB

For the first two arguments, I have to convert points into local space:

``````	const localPointB = BB.Vector3.TransformCoordinates(pointB, LINE_A.getWorldMatrix().invert())
const localPointC = BB.Vector3.TransformCoordinates(pointC, LINE_B.getWorldMatrix().invert())
``````

Now when I create my ball and socket joint, they seem to be connected at pointB, but when the physics run, they fling off in erratic directions and spin:

``````
const JOINT = new BB.BallAndSocketConstraint(
localPointB,
localPointC,
new BB.Vector3(1,1,1),
new BB.Vector3(1,1,1),
scene
)
``````

So I suppose I have to do something complicated for axisA and axisB

However already at this stage it seems needlessly weird and complicated by comparison to Ammo, Cannon etc…

Can you please provide a PG ?

2 Likes

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)

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
)

}

function createNextSocket(mesh) {

const aggre = new BB.PhysicsAggregate( mesh, BB.PhysicsShapeType.SPHERE, {
mass: settings.ballMass,
}, scene )

// EDGES DON'T COLLIDE (IMPORTANT)

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
)

}
``````
1 Like

Simpler version - `init` assumes that `pivot` is in world space (and not relative to either mesh):

``````
function getMeshPivot( pivot, mesh ) {
const matrix = mesh.getWorldMatrix().clone().invert()
const transformedPivot = BB.Vector3.TransformCoordinates(pivot.clone(), matrix)
return transformedPivot
}

function init( pivot, meshA, meshB ) {
constraint = new BB.BallAndSocketConstraint(
getMeshPivot(pivot, meshA),
getMeshPivot(pivot, meshB),
new BB.Vector3(1,1,1),
new BB.Vector3(1,1,1),
scene
)