放大到3D画面的空间选择框大到、画面、空间

2023-09-08 00:41:55 作者:那种心情你不了解

我想知道最好的算法,能够放大到屏幕空间选择框/窗口,在3D。

I wish to know the best algorithm to be able to zoom to a screen space selection box/window in 3D.

我有几分它目前的工作,但它似乎并没有放大正确的时候从目标的距离为显著。

I have it currently sort of working but it doesn't seem to zoom in correctly when the distance from the target is significant.

目前它的工作原理,通过判断相对于视口宽度/高度的选择框的规模和应用于的规模到相机到它的目标的距离/范围

Currently it works by figuring out the scale of the selection box relative to the viewport width/height and applies that scale to the distance/range of the camera to it's target.

推荐答案

其实这不是那么简单。看看这张图(这是一个2D投影为简单起见):

Actually it's not that simple. Look at this picture (it's a 2D projection for simplicity):

蓝色区域是当前摄像机的视锥。黄色区域是蓝色的平截头体覆盖的矩形选择屏幕的一部分。这样做的目的是使一个新的截锥其中最重presents黄色区域。问题是,什么样的方式应新的截锥适合黄色区域。

The blue area is the current camera's view frustum. The yellow area is a part of the blue frustum covered by the rectangular selection of the screen. The aim is to make a new frustum which best represents the yellow area. The problem is what way should the new frustum fit the yellow area.

一种可能性是psented在下面的图片$ P $:

One possibility is presented in the picture below:

新相机的视锥为紫色和相机的眼睛位于绿线。假设新相机已与原相同的属性(fovy,znear,​​zfar,方面),我们可以计算出新的位置和方向。

The new camera's view frustum is coloured purple and the camera's eye lies on the green line. Assuming the new camera has the same properties (fovy, znear, zfar, aspect) as the old one, we can compute its new position and direction.

现在计算一下:

的高度和宽度近平面的:

Height and width of the near plane:

h = 2 * tan(fovy/2) * znear
w = aspect * h

矩形的屏幕空间的坐标:

Screen-space coordinates of the rectangle:

rectangle = ( x0, y0, x1, y1 )

矩形的屏幕空间中心:

Screen-space center of the rectangle:

rcenter = ( (x0+x1)/2, (y0+y1)/2 )

另一幅图像澄清下一个计算:

Another image to clarify next calculations:

查看 - 空间矢量躺在附近的飞机,从近平面的中心到矩形的中心指向:

View-space vector lying on the near plane, pointing from the near plane's center to the rectangle's center:

center = ( (rcenter.x / screen_width  - 0.5) * w,
           (0.5 - rcenter.y / screen_height) * h, 0 )

然后,我们必须将这一载体,以世界空间:

Then we have to transform this vector to world-space:

centerWS = center.x * camera_right_dir + center.y * camera_up_dir

相机(dir2n)的新方向:

New direction of the camera (dir2n):

dir1 = camera_dir * znear
dir2 = dir1 + centerWS
dir2n = normalize(dir2)

相机(POS2)的新位置:

New position of the camera (pos2):

我做了一些假设,以简化计算。 大约有新旧近平面平行,所以:

I've made some assumptions, in order to simplify calculations. Approximately new and old near planes are parallel, so:

(w, h) / dist = (w * (x1-x0)/screen_width, h * (y1-y0)/screen_height) / znear
(1, 1) / dist = ( (x1-x0)/screen_width, (y1-y0)/screen_height) / znear
(1/dist, 1/dist) = ( (x1-x0)/screen_width, (y1-y0)/screen_height) / znear

因此​​:

dist = znear * screen_width / (x1-x0)

这应该等于:

Which should be equal to:

dist = znear * screen_height / (y1-y0)

这是只有在矩形有相同比例的屏幕,您可以通过锁定矩形的比例保证在用户绘制,或者你可以简单地只用矩形的宽度(真X1-X0),而忽略其高度(Y1-Y0),反之亦然。

That is true only if the rectangle has the same proportions as the screen, which you can guarantee by locking the rectangle's proportions while the user is drawing it, or you can simply use only the rectangle's width (x1-x0) and ignore its height (y1-y0) or vice versa.

最后:

pos2 = pos1 + dir2n * (dist-znear)