Solved it!
OK, three things:
- The rotation of the velocity wasn’t working. Used atan2 instead.
- I needed to switch the subtracting Y axes points getting the yOffset
- I needed to use .setVelocity(x, y, z) instead of .applyForce(x, y, z)
Here is the final script, hope it helps someone!
static getBallVelocity( ballPos, rimPos, angleDegrees, gravity ){
// Get angle in radians, from angleDegrees argument
const angle = THREE.Math.degToRad( angleDegrees );
gravity = gravity || 9.81;
// Positions of this object and the target on the same plane
const planarRimPos = new THREE.Vector3( rimPos.x, 0, rimPos.z ),
planarBallPos = new THREE.Vector3( ballPos.x, 0, ballPos.z );
// Planar distance between objects
const distance = planarRimPos.distanceTo( planarBallPos );
// Distance along the y axis between objects
const yOffset = ballPos.y - rimPos.y;
// Calculate velocity
const initialVelocity = ( 1 / Math.cos( angle ) ) * Math.sqrt( ( 0.5 * gravity * Math.pow( distance, 2 ) ) / ( distance * Math.tan( angle ) + yOffset ) ),
velocity = new THREE.Vector3( 0, initialVelocity * Math.sin( angle ), initialVelocity * Math.cos( angle ) );
// Rotate our velocity to match the direction between the two objects
const dy = planarRimPos.x - planarBallPos.x,
dx = planarRimPos.z - planarBallPos.z,
theta = Math.atan2( dy, dx ),
finalVelocity = velocity.applyAxisAngle( PopAShotAR.Vector3.up, theta )
return finalVelocity;
}