Multiple viewports Problem when involving Raycaster and TransformControl

Hi, I’m trying to implement an idea where the window is equally divided into left and right viewports. The right viewport has a raycaster to pick meshes and switch to TransformControl.

I use 1 div to contain the canvas, constructed 2 scene, 2 camera and 1 renderer.

In the screenshot above, the mesh in the right viewport is still within the red box. The mesh get picked when I click anywhere inside the red box. And I have to interact with TransformControl from the intersection line of the two viewports. I feel like there is only 1 view port and the mesh is in the center red box area.

I attempted to adjust the mouse coordinates by setting x = -2 when x < 0 to make the left viewport not interactable, but I still can’t find a way to handle the right viewport properly.

My guess is that if you do raycasting as specified in the docs, the code there assumes that the scene occupies the whole canvas and the canvas occupies the whole browser window. When the picking area is different, you have to adjust the calculation of the cursor position in NDC (normalized device coordinates).

2 Likes

@PavelBoytchev about to give you an education about viewports. :smiley:

1 Like

Yes, I code my scene based on docs raycaster section. I do think I have to adjust the NDC, that is the reason why I try to set NDC ‘x = -2’ when ‘x < 0’. But I don’t know how to do it right, I feel like the coordinates are messed up in my mind right now.

That will be great!

I think you will have to check which viewport the cursor is in, then base the coordinates on that viewport… by subtracting the top left of the viewport and dividing by width/height of that viewport, then doing the rest of the NDC computation.

That way you can use any viewports you want and it will still work.

Here is a demo of a single scene, shown in two viewports. When a model is picked (just hover the mouse pointer over it), it becomes red. Only the model in the right viewport can be picked, but both will become red, because they are the same object in the demo.

https://codepen.io/boytchev/full/PwqVrYK

Note that the NDC calculation is done with mapLinear. This is just to make it clearer what input coordinates to what output coordinates are mapped.

A general advice: it is always better to provide online demo that can be edited and debugged. This will make people easier to answer you. For example now I had to write a functional demo just to try whether my guess was correct.

6 Likes

I know I’m wrong but I came up with these

    left = event.clientX / 2
    pointer.x = ( event.clientX - left) /  (window.innerWidth / 2)
    // equal to clientX / window.innerWidth
    pointer.x = pointer.x * 2  - 1

exactly like the docs

let halfWidth = window.innerWidth/2;
pointer.x = event.clientX;
if(pointer.x >= halfWidth)pointer.x-=halfWidth;
pointer.x /= halfWidth;
pointer.x = pointer.x * 2 - 1;

( but… you should use @PavelBoytchev 's approach. )

1 Like

Thanks a million, both the code and the image are very helpful to understand the adjustment! I can now correctly pick mesh but I still have to do transformcontrol from the red line.


https://codepen.io/Constantine-Kong/pen/emNxwxp

I thought about make a online demo, but my code is in a bad shape. I should have provided one. :saluting_face:

Edit: I forgot save the changes, you can see the problem in the link now.

1 Like

Thanks now I know why I’m so stupid to came up with that equation. I treat the clientX as window.innerWidth just because clinetX ∈[0,window.innerWidth). I must have lost my mind.

1 Like

I know the feeling :smiley:

1 Like

Try this version:

https://codepen.io/boytchev/full/XJbGWmL

The issue was that TransformControls did not care about viewports, so I injected a few lines to make it work (lines 40-48). This is a fragment of the original function in the controls.

1 Like

This may be irrelevant but I noticed some odd behaviour, it looks like the raycaster still intersects the right hand view object if it is dragged into / partially into the left hand view…

1 Like

Yes, this is because the coordinates are not cut at the viewport (i.e. if you point to the left of the right half, the NDC would be less than -1). One if should be sufficient to filter out and raycast only when NDC∈[-1,1]

Edit: here is the x coordinate when I hover over the left half:

1 Like

Thanks! So we need to adjust the pointer of the TransformControl as well.

1 Like