【问题标题】:openGL set perspective camera distance based on bounding box on an ellipsoidal modelopenGL基于椭球模型上的边界框设置透视相机距离
【发布时间】:2014-08-17 17:03:33
【问题描述】:

我有一个透视相机,用于查看由地球模型组成的 3D 场景。地球模型是椭球体。我想根据模型上的某个边界框来概述这个模型,即基本上我想对这个 3D 模型做一个简单的 2D 概述。我想为此计算相机距离。

我实际上是在开放场景图中执行此操作,因此我可以获得所需场景/区域的 osg::BoundingBox。

我正在使用一种非常简单的方法来计算距离。

distanceVertical = ((boundingBox.yMax - boundingBox.ymin)/2.0)/ tan(fovy/2)
distanceHorizontal = ((boundingBox.xMax - boundingBox.xmin)/2.0)/ tan(fovx/2)

cameraDistance = max(distanceVertical, distanceHorizontal)

这个计算都是在世界空间中进行的,但不知怎的,它并没有给我正确的距离。我算错了吗?

【问题讨论】:

  • 什么距离错了?根据您提供的代码和我所记得的,distanceVertical 应该给您一个正确的值,假设 fovy 是您给相机的弧度版本,而 distanceHorizo​​ntal 应该是错误的。
  • 您的相机轴对齐是否像您的边界框?你给的 setProjectionMatrixAsPerspective 的值是多少?你的计算的输入和结果是什么,你期望什么(“它没有给我正确的距离”很模糊)?
  • @AlexandreVaillancourt 我最终尝试的是 1)从 (0,0,1) - z 轴到我的边界框中心生成一个旋转矩阵。 2)使用这个旋转矩阵旋转我原来的边界框的所有八个角。 3) 通过找到这些旋转点的 x,y,z 的最小值和最大值来计算一个新的边界框 4) cameraDistance1 = ((newbb.xmax - newbb.xmin)/2)/tan(fov/2) and cameraDistance2 = ((newbb.ymax - newbb.ymin)/2)/(tan(fov/2)xaspectRatio) 和 cameraDistance = max(cameraDistance1, cameraDistance2)。
  • @AlexandreVaillancourt 我不明白为什么我必须为 cameraDistance2 使用纵横比?我期望 cameraDistance 沿 x 而不是沿 y 的 aspectRatio ......但这个计算似乎有效!
  • 纵横比与fovy角度无关,它是相对于“height”相对于所述fovy角度。这就是为什么您必须相对于“距离”高度而不是 fovy 角度来计算 fovx

标签: opengl math graphics geometry openscenegraph


【解决方案1】:

请记住,您不能使用纵横比将 fovy(您提供给 setProjectionMatrixAsPerspective 的那个)直接转换为 fovx。这将假设投影是“弯曲的”,但事实并非如此,它投影在距相机平坦的距离处。

有了这些信息,您必须找到另一种方法来计算您的情况下的 x 大小 distanceHorizontal

由于您使用的是边界框,还请记住,这仅在相机位于与框中心对齐的 z 方向时才有效,因为边界框是轴对齐的。

// Assuming you fetch the aspectRatio and the fovy from the camera...
double aspectRatio = 1.0;
double fovy = degreeToRadian( 45.0 );
{
  double fovyDeg;
  double zNear; // discarded
  double zFar; // discarded
  camera->getProjectionMatrixAsPerspective( fovyDeg, aspectRatio, zNear, zFar );
  fovy = degreeToRadian( fovyDeg );
}


double halfSizeY = ((boundingBox.yMax - boundingBox.ymin) / 2.0);
double halfSizeX = ((boundingBox.xMax - boundingBox.xmin) / 2.0);

// Prevent a division by 0. 
if ( halfSizeX   == 0.0 ) halfSizeX   = 0.0001;
if ( aspectRatio == 0.0 ) aspectRatio = 0.0001;

double itemSizeRatio = halfSizeY / halfSizeX;
double distanceVertical   = halfSizeY / tan(fovy/2);
// The horizontal should be computed from the vertical value, and not from a fovx
double distanceHorizontal = distanceVertical * itemSizeRatio / aspectRatio;

cameraDistance = max(distanceVertical, distanceHorizontal);

我还没有尝试过这个解决方案,但我曾经不得不按照这些思路实施一些东西。这个逻辑似乎在纸上有效。

【讨论】:

  • 这个 distanceHorizo​​ntal 的计算是不是类似于 distanceHorizo​​ntal = ((boundingBox.xMax - boundingBox.xmin)/2.0)/ tan(fovx/2) where tan(fovx/2) = tan(fovy/2 )*纵横比?我还编辑了原始问题以包含更多图表,显示了我想要进行概述的更多边界框。如您所见,边界框主要沿 z 轴和 x 轴延伸...在这种情况下使用相同的 fov"y" 是否有效?
猜你喜欢
  • 2013-12-28
  • 2019-12-24
  • 1970-01-01
  • 2017-07-24
  • 2012-09-29
  • 2021-08-18
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多