3d 如何计算三维对象的视角

3d 如何计算三维对象的视角,3d,geometry,game-engine,coordinate-transformation,3d,Geometry,Game Engine,Coordinate Transformation,如下图所示,假设有一个虚拟摄影机指向一个对象,并且两者都是由相对于全局坐标系的方向和位置定义的。在图中,黑色表示地面军事系统,蓝色表示LCS 某些对象(如本例中的屏幕或LED)具有视角。例如,仅当与观察者的角度在±70°范围内时,才能看到它们 为了解决这个问题,到目前为止,我已经采取了以下伪代码演示的步骤。在适用的情况下,我们在右手坐标系中工作,使用以ZYX顺序应用的外部旋转 LEDToWorldTransform = LED.Transform; CameraToWorldTransform

如下图所示,假设有一个虚拟摄影机指向一个对象,并且两者都是由相对于全局坐标系的方向和位置定义的。在图中,黑色表示地面军事系统,蓝色表示LCS

某些对象(如本例中的屏幕或LED)具有视角。例如,仅当与观察者的角度在±70°范围内时,才能看到它们

为了解决这个问题,到目前为止,我已经采取了以下伪代码演示的步骤。在适用的情况下,我们在右手坐标系中工作,使用以ZYX顺序应用的外部旋转

LEDToWorldTransform = LED.Transform;
CameraToWorldTransform = Camera.Transform;
WorldToCameraTransform = CameraToWorldTransform.Inverse;
CameraToLEDTransform = WorldToCameraTransform * LEDToWorldTransform;
据我所知,CameraToLEDTransform现在应该包含LED相对于相机坐标系的平移和旋转。出于可视化目的:

现在这就是我被卡住的地方,看看
CameraToLEDTransform
的euler组件,我想我们可以得出结论,相对于相机坐标系旋转的Z组件不会影响LED的查看。我尝试了以下我不确定是否正确的方法。注意,在第三步中,我尝试反转其中一个Z轴的方向,使它们指向同一方向

R_Z, R_Y, R_X = CameraToLEDTransform.Rotation.Eulers
CameraToLEDTransform.Rotation.Eulers = 0, R_Y, R_X
CameraToLEDTransform.Rotation *= Rotation.AngleAxis[180deg,X]
Angle, Axis = CameraToLEDTransform.Rotation.AngleAxis
这给出了一个看起来正确的答案,但是我怀疑可能有错误,因为按照我的逻辑,我也应该能够将第三步替换为:

CameraToLEDTransform.Rotation *= Rotation.AngleAxis[180deg,Y]

然而,事实并非如此,我得到了一个不同的(当然是错误的)答案。这种方法可能是完全错误的,我当然不明白为什么在这种情况下绕X旋转180和绕Y旋转180不同。也许另一种方法是使用点积来计算角度,但是我认为这只适用于两个向量,而不是两个旋转。根据两个对象的方向投影两个新向量似乎是一种非常迂回的方法…

使用点积不是一种迂回的方法,它是正确的方法。您必须使用相机的视图方向向量和法线(即从观察者到相关LED/对象的向量)之间的点积来获得所需角度的余弦。如果对象是类似屏幕的曲面,则可能需要使用曲面的法线

// normalized returns a unit vector
Vector3 normal = (led.position - observer.position).Normalized(); 
Vector3 lookDirection = observer.lookDirection; // Should be a unit vector

float cosAngle = Vector3.Dot(normal, lookDirection);
在检查角度是否在所需范围内时,我们可以使用
cos
函数的以下属性来避免
acos
调用:


如果
-角度正确。我从一些错误的假设开始,这让我走上了错误的道路。
// You can constantize or precompute this
float cosViewingAngle = cos(deg2rad(70));
bool inViewingAngle = cosAngle >= cosViewingAngle;