What is the normal for my use in GetAngleBetweenVectors?

I’m making a VR Grab/rotate thing and so each frame I have the position of the pointer newPoint and the previous frame’s position prevPoint and an object that is going to be rotated model. I’m trying to use GetAngleBetweenVectors to get the angle to rotate the object.
For the sake of simplicity, I’m hard coding the rotation to be only the Forward axis. The pivot point is moved to the corner so it’s basically a lid that opens to the right, like so:

Here’s what my code looks like so far:

const origin = model.getAbsolutePivotPoint().clone()
scene.onBeforeRenderObservable.add(() => {
            const prevPoint = model.props.prevPoint
            const newPoint = pointerMesh.absolutePosition.clone()
            if (prevPoint.equals(newPoint)) return // To avoid a bug
            const zAngle = Vector3.GetAngleBetweenVectors(
                prevPoint.subtract(origin),
                newPoint.subtract(origin),
                Vector3.Forward()
            )
            model.rotate(model.forward, zAngle)
            model.props.prevPoint = newPoint
        })

Unfortunately this is changing the amount of rotation based on my Z position. I know I have the third parameter of the GetAngleBetweenVectors function incorrect, but I don’t know what the normal should be for this case.

I’ll note that this code works as expected:

scene.onBeforeRenderObservable.add(() => {
    const prevPoint = model.props.prevPoint
    const newPoint = pointerMesh.absolutePosition.clone().subtract(origin)
    prevPoint.z = 0
    newPoint.z = 0
    if (prevPoint.equals(newPoint)) return // To avoid a bug
    const zAngle = Vector3.GetAngleBetweenVectors(
        prevPoint,
        newPoint,
        model.forward
    )
    model.rotate(model.forward, zAngle)
    model.props.prevPoint = newPoint
})

But setting the z to 0 is a bit too hard coded. Is there a way to project the Vector3s onto model.forward for this?

Given two vector3s v0 and v1 the a normal, N, to the plane containing v0 and v1 can be found using

N = BABYLON.Vector3.Cross(v0, v1);

swapping v0 and v1 with give the normal in the opposite direction and hence changes the angle direction.

1 Like

I had a lot of scratch code in a Playground to test stuff out and get an understanding, but twice I’ve hit alt-left and lost everything. Anyway, the result I’ve found is if I project the vectors onto the axis I get the results I expect. Here’s how it looks

const prevPoint = model.props.prevPoint
const newPoint = pointerMesh.absolutePosition.clone().subtract(origin)
prevPoint.z = 0
newPoint.z = 0
if (prevPoint.equals(newPoint)) return // To avoid a bug
const projectedNewPoint = newPoint.subtract(model.forward.scale(Vector3.Dot(newPoint, model.forward)))
const projectedPrevPoint = prevPoint.subtract(model.forward.scale(Vector3.Dot(prevPoint, model.forward)))
const zAngle = Vector3.GetAngleBetweenVectors(
    projectedPrevPoint,
    projectedNewPoint,
    model.forward
)
model.rotate(model.forward, zAngle)
model.props.prevPoint = newPoint
1 Like