useScroll bounces back to start of curve when there is damping


I have a handcar that is running along a curve, that moves every time you scroll. The scroll is set to infinite. However, at the very end of the curve it does not just smoothly run over the ends of the curve as I had expected. Instead, after reaching a curve.offset of 1, it bounces back to 0, interrupting the smooth damping.

curve.range(0, 400/400) stays on 0 for 5 frames or so, while curve.offset shows negative values. The image below uses curve.offset.

Here is my code:

       function setRideFunc( car, time, trajectory, forward, up, pos, nextPos, futurePos, matrix ) {

        trajectory.getPointAt( time%1, pos );
        trajectory.getPointAt( (time+0.0001)%1, nextPos );
        trajectory.getPointAt( (time+0.0002)%1, futurePos );
        forward.subVectors( nextPos, pos ).normalize();
        up.subVectors( futurePos, nextPos ).normalize();
        up.y += 1;
        matrix.lookAt( pos, nextPos, up);
        car.quaternion.setFromRotationMatrix( matrix );
        car.position.copy( pos );

    useFrame((state, delta) => {
        const currentPointIndex = Math.min(
            Math.round(Math.sign(scroll.offset) === -1 ? -scroll.offset * 400 : scroll.offset * 400),
            400 - 1
        let pos = new THREE.Vector3();
		let nextPos = new THREE.Vector3();
		let futurePos = new THREE.Vector3();
		let forward = new THREE.Vector3();
		let up = new THREE.Vector3();
		let matrix = new THREE.Matrix4();
        setRideFunc(handcarRef.current, currentPointIndex / 400, curve, forward, up, pos, nextPos, futurePos, matrix)

I am not sure how else to fix this issue besides setting damping to 0.

Thank you for your help.

Edit: My apologies, here is the codesandbox. The RailsCurve and Handcar are where the problem is most likely located.

1 Like

Please post a working example in a codepen/fiddle/glitch

What is setRideFunc? There isn’t enough info here.
You should be able to just clamp your interpolant somewhere to 0 to 1.

I edited my posted question, adding the codesandbox link. I am not sure why it doesn’t just remain within that range.

This looks sus:

    trajectory.getPointAt(time % 1, pos);
    trajectory.getPointAt((time + 0.0001) % 1, nextPos);

    trajectory.getPointAt((time + 0.0002) % 1, futurePos);

You want to clamp that value instead of % 1 ing it.

let ctime = min(1,time);
  trajectory.getPointAt(ctime, pos);
  trajectory.getPointAt((ctime + 0.0001) , nextPos);
  trajectory.getPointAt((ctime + 0.0002) , futurePos);
1 Like

Another 3D component really doesn’t like me changing the function. When I do, it says “Uncaught TypeError: Cannot read properties of undefined (reading ‘distanceToSquared’)”, so I am going to add that to my codepen.