不变尺度几何

Invariant scale geometry

我正在编写一个网格编辑器,我在其中使用操纵器更改网格的顶点。任务是渲染具有恒定尺寸的操纵器,这些尺寸在更改相机和视口参数时不会改变。投影矩阵是透视的。对于如何实现不变比例几何的想法,我将不胜感激。

如果我没看错,您想渲染一些标记(例如顶点拖动编辑区域),对于它们渲染到的任何深度都具有相同的视觉大小。

有两种方法:

  1. 随深度缩放

    计算相机视图的垂直距离(简单的点积)并缩放标记大小,使其具有相同的视觉大小不变的深度。

    所以如果P0是你的相机位置,Z是你的相机视角方向单位向量(通常是Z轴)。然后对于任何位置 P 像这样计算比例:

    depth = dot(P-P0,Z)
    

    现在,比例取决于在某些指定 depth0 处想要的视觉效果 size0。现在使用我们想要的三角形相似度:

    size/dept = size0/depth0
    size = size0*depth/depth0
    

    所以用 size 或比例 depth/depth0 渲染你的标记。如果使用缩放,你需要围绕你的目标位置缩放 P 否则你的标记会移动到两侧(所以平移,缩放,平移回来)。

  2. 计算屏幕位置并使用非透视渲染

    因此,您以与图形管道相同的方式转换目标坐标,直到获得屏幕 x,y 位置。记住它,并且通过这将使您的标记只使用它而不是真实位置。对于此渲染过程,要么使用一些恒定深度(与相机的距离),要么使用非透视图矩阵。

有关详细信息,请参阅

[Edit1] 像素大小

您需要为此使用 FOVx,FOVy 投影角度和 view/screen 分辨率 (xs,ys)。这意味着如果深度为 znear 且坐标为角度的一半,则投影坐标将转到屏幕边缘:

tan(FOVx/2) = (xs/2)*pixelx/znear
tan(FOVy/2) = (ys/2)*pixely/znear
---------------------------------
pixelx = 2*znear*tan(FOVx/2)/xs
pixely = 2*znear*tan(FOVy/2)/ys

其中 pixelx,pixely 是表示深度 znear 处视觉上单个像素的大小(每轴)。如果展位大小相同(因此像素是正方形),您便拥有了所需的一切。如果它们不相等(像素不是正方形),那么您需要在屏幕轴对齐坐标中渲染标记,因此方法 #2 更适合这种情况。

因此,如果您选择 depth0=znear,那么您可以将 size0 设置为 n*pixelx and/or n*pixely 以获得 n 的视觉大小像素。或者使用任何 dept0 并将计算重写为:

pixelx = 2*depth0*tan(FOVx/2)/xs
pixely = 2*depth0*tan(FOVy/2)/ys

补充一下:

size0x = size_in_pixels*(2*depth0*tan(FOVx/2)/xs)
size0y = size_in_pixels*(2*depth0*tan(FOVy/2)/ys)
-------------------------------------------------
sizex = size_in_pixels*(2*depth0*tan(FOVx/2)/xs)*(depth/depth0)
sizey = size_in_pixels*(2*depth0*tan(FOVy/2)/ys)*(depth/depth0)
---------------------------------------------------------------
sizex = size_in_pixels*(2*tan(FOVx/2)/xs)*(depth)
sizey = size_in_pixels*(2*tan(FOVy/2)/ys)*(depth)
---------------------------------------------------------------
sizex = size_in_pixels*2*depth*tan(FOVx/2)/xs
sizey = size_in_pixels*2*depth*tan(FOVy/2)/ys