不变尺度几何

inn*_*nti 4 opengl algorithm directx geometry

我正在编写一个网格编辑器,其中有操纵器,可以在其帮助下更改网格的顶点。任务是渲染具有恒定尺寸的操纵器,当更改相机和视口参数时,该尺寸不会改变。投影矩阵是透视矩阵。我将感谢您提供如何实现不变比例几何的想法。

Spe*_*tre 5

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

有两种方法:

  1. 随深度扩展

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

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

    depth = dot(P-P0,Z)
    
    Run Code Online (Sandbox Code Playgroud)

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

    size/dept = size0/depth0
    size = size0*depth/depth0
    
    Run Code Online (Sandbox Code Playgroud)

    size所以用或 scale渲染你的标记depth/depth0。如果使用缩放,您需要围绕目标位置进行缩放P,否则您的标记将移动到两侧(因此平移、缩放、向后平移)。

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

    因此,您可以像图形管道一样变换目标坐标,直到获得屏幕x,y位置。请记住这一点,并且在传递过程中,您的标记将仅使用它而不是真实位置。对于此渲染通道,可以使用一些恒定的深度(距相机的距离)或使用非透视视图矩阵。

有关详细信息,请参阅了解 4x4 齐次变换矩阵

[编辑1]像素大小

FOVx,FOVy为此,您需要使用投影角度和视图/屏幕分辨率(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
Run Code Online (Sandbox Code Playgroud)

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

因此,如果您选择depth0=znear,则可以设置size0n*pixelx和/或n*pixely获取n像素的视觉大小。或者使用 anydept0并将计算重写为:

pixelx = 2*depth0*tan(FOVx/2)/xs
pixely = 2*depth0*tan(FOVy/2)/ys
Run Code Online (Sandbox Code Playgroud)

只是为了完整:

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
Run Code Online (Sandbox Code Playgroud)