3d适合在viewport的模型

时间:2009-05-18 13:14:50

标签: opengl

3D模型如何以单位方式处理? 当我有一个随机模型,我想在我的视图端口,我不知道,如果它太大或不,如果我需要翻译它在中间...
我认为一个3d对象可能有它自己的起源。

3 个答案:

答案 0 :(得分:2)

您需要找到一个边界体,一个包围所有对象顶点的形状,用于比对象本身更易于使用的对象。通常使用球体。艺术家可以将球体定义为模型信息的一部分,也可以在运行时进行处理。计算最佳球体非常困难,但您可以使用以下方法获得良好的近似值:

determine the min and max value of each point's x, y and z
  for each vertex
    min_x = min (min_x, vertex.x)
    max_x = max (max_x, vertex.x)
    min_y = min (min_y, vertex.y)
    max_y = max (max_y, vertex.y)
    min_z = min (min_z, vertex.z)
    max_z = max (max_z, vertex.z)

sphere centre = (max_x + min_x) / 2, (max_y + min_y) / 2, (max_z + min_z) / 2
sphere radius = distance from centre to (max_x, max_y, max_z)

使用此球体,确定一个允许全部查看球体的世界位置 - 简单几何体将决定这一点。

答案 1 :(得分:0)

对不起,你的问题很不清楚。我想你想要将3D模型居中到视口。您可以通过计算模型的边界框来实现此目的。为此,遍历所有多边形并获得最小/最大X / Y / Z坐标。点(min_x,min_y,min_z)(max_x,max_y,max_z)给出的边界框将包含整个模型。现在,您可以通过查看此框的中心来使模型居中。通过一些进一步的计算(取决于您的FOV),您还可以在视口内获得左/右/上/下边框。

答案 2 :(得分:0)

"所以我试图将其缩小"

在这种情况下,最好的办法就是不要改变你的模型!留下吧。你要改变的是你的相机。

首先在3D空间的某处计算模型的边界框。

接下来通过取max来计算它的半径(aabb.max.x-aabb.min.x,aabb.max.y-aabb.min.y,aabb.max.z-aabb.min.z) 。这是原油,但它完成了工作。

要将对象置于视口中心,请将相机放在对象位置。如果Y是您的前轴,则从Y减去半径。如果Z是前轴,则从中减去半径。减去一个软糖因子让你经过讨厌的近平面,这样你的模型就不会被剪掉。我在我的引擎中使用了一个很好的lookat()方法的四元数。所以调用lookat()并传入边界框的中心。瞧!您的对象在视口中居中,无论它在世界的哪个位置。

这总是将摄像机轴对齐,因此您可能希望获得想象并将摄像机转换为模型空间,减去半径,然后再次查看()中心。然后你总是在看模型的背面。关键始终是lookat()。

这是我的引擎中的一些示例代码。它会检查我们是否正在尝试构建一块静态地形,如果这样,则从高处向下看,或者从光线或静态网格向下看。视觉是在场景中绘制的任何东西,并且有许多不同类型。 Visual :: Instance是视觉的副本,或者绘制它的位置。

void EnvironmentView::frameSelected(){
  if( m_tSelection.toInstance() ){
    Visual::Instance& I = m_tSelection.toInstance().cast();
    Visual* pVisual = I.toVisual();
    if( pVisual->isa( StaticTerrain::classid )){
      toEditorCamera().toL2W().setPosition( pt3( 0, 0, 50000 ));
      toEditorCamera().lookat( pt3( 0 ));
    }else if( I.toFlags()->bIsLight ){
      Visual::LightInstance& L = static_cast<Visual::LightInstance&>( I );
      qst3& L2W = L.toL2W();
      const sphere s( L2W.toPosition(), L2W.toScale() );
      const f32 y =-(s.toCenter()+s.toRadius()).y();
      const f32 z = (s.toCenter()+s.toRadius()).y();
      qst3& camL2W = toEditorCamera().toL2W();
      camL2W.setPosition(s.toCenter()+pt3( 0, y, z ));//45 deg above
      toEditorCamera().lookat( s.toCenter() );
    }else{
      Mesh::handle hMesh = pVisual->getMesh();
      if( hMesh ){
        qst3& L2W = m_tSelection.toInstance()->toL2W();
        vec4x4 M;
        L2W.getMatrix( M );
        aabb3 b0 = hMesh->toBounds();
        b0.min = M * b0.min;
        b0.max = M * b0.max;
        aabb3 b1;
        b1 += b0.min;
        b1 += b0.max;
        const sphere s( b1.toSphere() );
        const f32 y =-(s.toCenter()+s.toRadius()*2.5f).y();
        const f32 z = (s.toCenter()+s.toRadius()*2.5f).y();
        qst3& camL2W = toEditorCamera().toL2W();
        camL2W.setPosition( L2W.toPosition()+pt3( 0, y, z ));//45 deg above
        toEditorCamera().lookat( b1.toOrigin() );
      }
    }
  }
}