I am using rapier physics with R3f, using pmndrs Ecctrl.
// returns the current player position or a default position
const calculatePosition = useCallback((pos, addMe) => {
if (ecctrlRef.current) {
try {
const { x, y, z } = ecctrlRef.current.translation()
if (addMe) {
const [a, b, c] = addMe
return [x + a, y + b, z + c]
}
return [x, y, z]
} catch (err) {
}
}
return pos
}, [])
const [cameraRotation, setCameraRotation] = useState([0,0,0])
const calculateRotation = useCallback(([x, y, z]) => {
const [cx, cy, cz] = cameraRotation
return [x + cx, y + cy, z +cz]
})
const objectRefs = useRef([])
const [objects, setObjects] = useState([])
const calculateVelocity = ([rx, ry, rz], mag = 0) => {
const destX = Math.sin(ry) * mag
const destY = Math.sin(rx) * mag
const destZ = Math.cos(ry) * mag
return [destX, destY, destZ]
}
const createObject = () => {
const rotation = calculateRotation([0, 0, 0])
return {
id: Math.random() + '',
position: calculatePosition([0, 2, 1], [0, 0, 1]),
velocity: calculateVelocity(rotation, 3),
color: (0xffffff - Math.random() * 0x444444),
}
}
const throwObject = () => {
setObjects(obj => ([...obj, createObject()]))
}
const GetCameraData = ({ setCameraRotation }) => {
useFrame(({ camera }) => {
const { x, y, z } = camera.rotation
setCameraRotation([x, y, z])
})
return null
}
const RigidSphere = ({ velocity = [0, 1, 0], position = [0, 0, 0], color = 0xffffff }) => {
const ref = useRef()
const [thrown, setThrown] = useState(false)
useFrame(() => {
if (!thrown) {
const [x, y, z] = velocity
ref.current.addForce({ x, y, z }, true)
setThrown(true)
} else {
ref.current.resetForces(true)
}
})
return <RigidBody ref={ref} colliders="ball">
<Sphere scale={0.1} position={position}>
<meshLambertMaterial color={color} />
</Sphere>
</RigidBody>
}
rendering
<Canvas
shadows
linear
flat
onPointerDown={(e) => {
if (currentLevelData.type === ECCTRL) {
if (e.pointerType === "mouse") {
try {
e.target.requestPointerLock();
} catch (err) {
console.warn('unable to get pointer lock', err)
}
}
}
}}
onPointerUp={(e) => {
if (level === MINIGAME_THROW) {
throwObject()
}
}}
>
Suspense fallback={null}>
<Physics timeStep="vary">
{levelJsx}
{objects.map((props) => <RigidSphere key={props.id} {...props} />)}
</Physics>
</Suspense>}
<GetCameraData setCameraRotation={setCameraRotation}/>
</Canvas>
Specifically I’m struggling with the math for calculateVelocity
.
I’m passing in an Euler x, y, z rotation and a magnitude, at which to throw the Sphere. I want to calculate the velocity I need to give the rigidBody.addForce(velocity, wakeUp)
but I’m not sure on the maths.
Thanks.