Multiple Views Raycasting TransformControls

hi everyone!

I am trying to show multiple views on the same renderer like:

https://threejs.org/examples/webgl_multiple_views

In each view I am trying to perform object picking/raycasting once an object is picked in the specific view, I’d like to attach the THREE.TransformControls. It only works in the 2nd in the middle but not the others. Can you please help?

It’s a bit hard to help you without debugging your code. You might want to demonstrate the issue as a live example.

In any event, the mentioned example uses a perspective matrix per view. You have to ensure to THREE.TransformControls with the correct camera, otherwise the interaction won’t work correctly.


I have a teapot object and then…
raycaster = new THREE.Raycaster();

 renderer = new THREE.WebGLRenderer();
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

             control = new THREE.TransformControls( camera, renderer.domElement );

            control.addEventListener( 'change', render );

            scene.add( control );
            renderer.domElement.addEventListener( 'mousedown', clickEvent );

        function clickEvent( event ) {
            var elem = renderer.domElement,
                boundingRect = elem.getBoundingClientRect(),
                x = (event.clientX - boundingRect.left) * (elem.width / boundingRect.width),
                y = (event.clientY - boundingRect.top) * (elem.height / boundingRect.height);
			//1st view
            var view = tripleViews[1];
           camera = view.camera;
            var WIDTH = Math.floor(windowWidth * view.width);
            var HEIGHT = Math.floor(windowHeight * view.height);

            mouse.x = ( x / WIDTH ) * 2 - 1;
            mouse.y = - ( y / HEIGHT ) * 2 + 1;

            raycaster.setFromCamera( mouse, camera );
            var intersects = raycaster.intersectObjects( scene.children );
            if ( intersects.length > 0 ) {
                if ( INTERSECTED != intersects[ 0 ].object ) {
                    INTERSECTED = intersects[ 0 ].object;

                    if ( control.object === undefined || control.object !== INTERSECTED ) {
                        control.attach( INTERSECTED );
                    }
                }
            }

            render();
        }
the transform controls only work in the 2nd viewport. Here are the configurations for my viewport.


            var tripleViews = [
				{
					left: 0,
					bottom: 0,
					width: 0.33,
					height: 1.0,
					background: new THREE.Color( 0.8, 0.9, 1.0 ),
					eye: [ 0, 300, 1200 ],
					up: [ 0, 1, 0 ],
					fov: 70,
					updateCamera: function ( camera, scene, mouseX ) {

				//	 camera.position.x += mouseX * 0.05;
                        // 	camera.position.x = Math.max( Math.min( camera.position.x, 2000 ), - 2000 );
					  camera.lookAt( scene.position );
                      		  //  background: new THREE.Color( 0.2, 0.9, 1.0 );
					}
				},
				{
					left: 0.33,
					bottom: 0,
					width: 0.34,
					height: 1,
					background: new THREE.Color( 1.0, 0.8, 0.9 ),
					eye: [ 0, 1800, 0 ],
					up: [1, 0, 0 ],
					fov: 45,
					updateCamera: function ( camera, scene, mouseX ) {
                        //camera.position.x -= mouseX * 0.05;
                        //camera.position.x = Math.max( Math.min( camera.position.x, 2000 ), - 2000 );
					  camera.lookAt( camera.position.clone().setY( 0 ) );


					}
				},
				{
					left: 0.66,
					bottom: 0,
					width: 0.34,
					height: 1,
					background: new THREE.Color( 0.7, 0.897,  0.5),
					eye: [ 1400, 800, 0 ],
					up: [ 0, 1, 0 ],
					fov: 60,
					updateCamera: function ( camera, scene, mouseX ) {

				//	  camera.position.y -= mouseX * 0.05;
				///	  camera.position.y = Math.max( Math.min( camera.position.y, 1600 ), - 1600 );
					  camera.lookAt( scene.position );

					}
				}
			];

I  also just want to use the world coordinates. Please help!
1 Like

How can transformcontrols be only applied to specific viewport within the same scene?

I’m not sure I understand this question. When you transform an object with the controls, you will see this effect in all of your views. Remember, that you don’t transform the camera but the object itself.

Thank you so much for taking the time to help! @Mugen87
Although the effect will be seen in all the views, if the controls in the 1st viewport is moved it should only move in the X direction. Likewise the controls in the 2nd viewport is moved, then only the object should move in the Y direction. We don’t have to worry about the 3rd viewport because it would just be a display. Can you please help me? I am able to find when the intersections happened with each viewport with the following code:

// 1st viewport
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 1;

// 2nd viewport
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;

// 3rd viewport
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 6 - 5;

mouse.y = - ( event.clientY / renderer.domElement.clientHeight) * 2 + 1;

Even though I can detect when my mouse intersects the object at that particular viewpoint, I still cannot used the transformcontrols in all of the viewports individually.

I was also considering using DragControls but I am not sure how to restrict the drag to a particular X or Y plane in each viewport. I really appreciate your suggestions.

I think the issue stems from the internal function getPointer for TransformControls.

It is hardcoded to use the dimensions of the HTML canvas. There doesn’t appear to be a way to do any override or supply options to factor for when you use renderer.setViewport and renderer.setScissor a new coordinate space is create.

1 Like

The initial question seems to be about something different, but this is the part

that I have encountered, I am using renderer.setViewport and renderer.setScissor and my mesh is in the centres of two parts of the renderer, the problem is that the transform handles trigger as if they are in the center of the whole canvas. Has anyone found a way to deal with it? @Mugen87 maybe you can help, please!

@kavikode did you get the solution for this? Can you explain? Thanks

Was there ever a solution to this? It appears transformControls does not work with multiple viewports ?

The only solution I could come up with is in the render loop convert mouse coordiantes to the viewport hovered on and then use raycaster.setFromCamera(mouse, camera). However this really hurts performance as the mouse coordiantes are constantly being converted and the transform controls picking is finicky.

example shown here using react-three-fibre. Click on an object to add transform controls. Only the middle panel works with the controls.