在OpenGL中调整大小时保持纵横比

4
我实现了以下代码:
void TestGlPlot::resizeGL(int width, int height) 
{
   setupViewport(width, height);
}

void TestGlPlot::setupViewport(int width, int height)
{
   /* Prevent divide by zero --------------------------------------------------------------------*/
   if (height == 0) height = 1;
   /* Calculate aspect ratio --------------------------------------------------------------------*/
   float aspectRatio = (float)width / (float)height;

   /* Set viewport to cover the window ----------------------------------------------------------*/
   glViewport(0, 0, width, height);

   /* Set aspect ratio --------------------------------------------------------------------------*/
   glMatrixMode(GL_PROJECTION); /* switch to projection matrix */
   glLoadIdentity();
   /*
   if (width >= height)
   {
   gluOrtho2D(-0.5*aspectRatio, 0.5*aspectRatio, 0.0, 1.0);
   }
   else
   {
   gluOrtho2D(-0.5, 0.5, 0.0*aspectRatio, 1.0*aspectRatio);
   }
   glMatrixMode(GL_MODELVIEW);
   */
   gluOrtho2D(-1, 1, 0.0, 1.0);
   glMatrixMode(GL_MODELVIEW);
}

void TestGlPlot::paintEvent(QPaintEvent *event) {
   makeCurrent();
   setupViewport(width(), height());

   glMatrixMode(GL_MODELVIEW);

   /* Set white background ----------------------------------------------------------------------*/
   glClear(GL_COLOR_BUFFER_BIT);
   glClearColor(255,255,255,0);

   /* Paint OpenGL events -----------------------------------------------------------------------*/
   glColor4f(1.0, 0.0, 0.0, 1.0);

   /* light grey */
   glColor4f(0.0, 0.0, 0.0, 0.3); 
   gluPartialDisk(plainQuad, 0.1, 1, 20, 4, -60, 120);

   /* Paint QPainter events ---------------------------------------------------------------------*/
   QPainter painter(this);

   /* Draw grey border around plot --------------------------------------------------------------*/
   painter.setPen(QColor("#808080"));
   painter.drawRect(0, 0, width()-1, height()-1);

   painter.setFont(font);

   /* Translate coordinate system to (0,0) center -----------------------------------------------*/
   QMatrix m;
   m.translate(width()*0.5, height()*0.5);   
   painter.setMatrix(m);

   /* Left side descriptions for radius ---------------------------------------------------------*/
   painter.drawText(-0.17*width(), 0.38*height(), tr("100m"));
   painter.drawText(-0.27*width(), 0.28*height(), tr("200m"));
   painter.drawText(-0.37*width(), 0.18*height(), tr("300m"));
   painter.drawText(-0.47*width(), 0.08*height(), tr("400m"));

   painter.drawText(0.45*width(), -0.01*height(), tr("60°"));
   painter.drawText(0.26*width(), -0.38*height(), tr("30°"));

   painter.drawText(-0.47*width(), -0.01*height(), tr("300°"));
   painter.drawText(-0.28*width(), -0.38*height(), tr("330°"));

   painter.end();
}

我尝试过不同的调整大小方法(保持partialDisk对象的形状而不拉伸它),但每种方法都失败了。我还想保持单位圆的坐标处理方式(这样我就可以将我的测量值归一化并绘制到极坐标图中)。

1个回答

2
为保持纵横比,通常有几种选项:
  1. 始终按比例缩放到一个维度。例如,您只需定义要始终查看的水平范围[-0.5,0.5]。在这种情况下,您必须通过因子(1 / aspect_viewport)来校正垂直范围。
  2. 使用某种等效的letterboxing。因此,您定义了一个“感兴趣的区域”,您总是希望完全看到该区域,但可能会在宽度或高度上看到更多内容,具体取决于窗口纵横比(基本上相当于观看letterboxed电影时的黑色条)。有两种情况需要考虑:视口的纵横比大于您的区域的纵横比,因此它更宽。在这种情况下,您应该映射整个高度,并将水平范围增加一个因子(aspect_viewport / aspect_region)。否则,窗口的纵横比低于您的区域的纵横比,因此您应该使用全部宽度并将垂直范围扩大(aspect_region / aspect_viewport)。请注意,在两种情况下,因子都大于或等于1。

在您的代码中,您几乎已经实现了方法2,但是您错误地处理了aspectRatio < 1的情况,它应该是

   if (width >= height)
           gluOrtho2D(-0.5f*aspectRatio, 0.5f*aspectRatio, 0.0f, 1.0f); 
   else 
           gluOrtho2D(-0.5f, 0.5f, 0.0, 1.0/aspectRatio);

感谢您的帮助。现在渲染的图像在调整大小时不会拉伸,但是它被压缩而没有调整大小。我认为我必须适应plainQuad的比例,以便于gluPartialDisk(plainQuad, 0.1, 1, 20, 4, -60, 120)。 - omgodie
如果我只是使用您建议的更改,通过aspectRatio进行划分,渲染的部分圆盘会延伸到剪辑区域之外(这是合理的,因为外半径为1.0f,而剪辑区域止于0.5f)。 - omgodie
我还想提一下,当我选择:gluOrtho2D(-1.0faspectRatio, 1.0faspectRatio, 1.0f, 1.0f); 时,一切都正常工作,但图像较小,我只想看到窗口的顶部部分,并且它应相应地调整大小(我所说的顶部部分是指x从-1.0到+1.0,y从0.0到+1.0的所有内容)。 - omgodie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接