Y position at a certain x position of a moving tubegeomerty

I am very new with three.js and I wanted to do something that looked simple.
I wanted to generate a tube that follows some data points (a sinewave for now) and shift this to the left with a certain speed ( x seconds) . That seems to work but then I want a box, sphere or whatever mesh to not move to the left (x-axis) but only follow the y values (height) of the moving tube. Like if you would shine a spotlight on it. Because I have no clue what the y value is on the path at a certain x value I want to use the raycaster, I looked it up from a few samples etc but I cannot get it to work. Can someone help with this raycaster (see attached code) or has another idea of calculating the y value at a certain x inside the path of a tubegeomerty ? I also tried path.getPointAt(x); but that probably only gives a point at a certain length of the path between 0…1
index.html (2.3 KB)

My first three.js app body { margin: 0; }
	    class CustomSinCurve extends THREE.Curve {
			constructor( scale = 1 ) {

				super();

				this.scale = scale;

			}

			getPoint( t, optionalTarget = new THREE.Vector3() ) {

				const tx = t * 3 - 1.5;
				const ty = Math.sin( 2 * Math.PI * t );
				const tz = 0;

				return optionalTarget.set( tx, ty, tz ).multiplyScalar( this.scale );

			}

		}
	
		// Our Javascript will go here.
		const scene = new THREE.Scene();
		const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

		const renderer = new THREE.WebGLRenderer();
		renderer.setSize( window.innerWidth, window.innerHeight );
		document.body.appendChild( renderer.domElement );
		const geometry = new THREE.BoxGeometry( 1, 1, 1 );
		const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
		const cube = new THREE.Mesh( geometry, material );
		scene.add( cube );
		
		

		const path = new CustomSinCurve( 10 );
		const geometryPipe = new THREE.TubeGeometry( path, 70, 2, 16, false );
		const materialPipe = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
		const meshPipe = new THREE.Mesh( geometryPipe, materialPipe );
		scene.add( meshPipe );

        // Add some lighting to the scene
		var light = new THREE.PointLight( 0xffffff, 1, 100 );
		light.position.set( 5, 5, 5 );
		scene.add( light );
		
		camera.position.z = 50;
		
		function animate() {
			requestAnimationFrame( animate );
			cube.rotation.x += 0.01;
			cube.rotation.y += 0.01;
			
			meshPipe.position.x -= 0.1;
			
			// Create a new raycaster
			var raycaster = new THREE.Raycaster();

			// Set the origin of the ray to the x value you're looking for
			var x = 0;
			raycaster.set(new THREE.Vector3(x, 0, 0), new THREE.Vector3(0, 1, 0));

			// Check if the ray intersects with the tube
			var intersects = raycaster.intersectObject(meshPipe);
			if (intersects.length > 0) {
				var y = intersects[0].point.y;
				console.log(y);
			}

			
			
			renderer.render( scene, camera );
		}
		animate();
	</script>
</body>

You should not constantly create new objects in animate.

new THREE.Raycaster()
(new THREE.Vector3(x, 0, 0), new THREE.Vector3(0, 1, 0))

You can create them once and then use them.

Take a look at the beginner example step 10 from the collection.

see also
RaycastingToLine
RaycasterAfterUpdatingPositions

getPointAt afaict, takes in a unit from 0 to 1 and gives out a vector in world coordinates at the given unit, so 0.5 would return a world coordinate vector3 half way along the curve. As @hofk has mentioned its probably best to create this vector once and have getPointAt update it as needed…

Thanks ! , these examples look amazing, since I am brand new to three.js I will get through them. The RaycastingToLine is a really helpfull for my project. I am going to try to make it work that way.

Maybe this older example is also helpful?

eXtended eXamples Modify indexed BufferGeometry - @author hofk

see line 548 function onContainerMouseDown( event ) { ...

Yes, thank you. All examples are helpfull !