Keeping aspect ratio when resizing in OpenGL

那年仲夏 提交于 2019-12-07 07:56:54

问题


I implemented the following code:

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();
}

i tried different methods for resize handling (keeping the shape of the partialDisk object without stretching it) but every method failed. I also want to keep the coordinate handling of the unit-circle (so i can normalize my measurements and draw them into a polar-plot).


回答1:


To keep the aspect ratio, you have several options in general:

  1. Always scale to one dimension. For example, you just define that you want always see the horizontal range [-0.5,0.5]. In this case, you have to correct the vertical range by the factor (1/aspect_viewport).
  2. Use some equivalent of letterboxing. So you define a "region of interest" which you always want to see completely, but you might see more in width or height, depending on the window aspect (that would be basically equivalent to the black bars when watching letterboxed movies). There are two cases to consider: the aspect of the viewport is greater than the aspect of your region, so it is wider. In that case, you should map the full height and increase the horitonal range by a factor of (aspect_viewport/aspect_region). Otherwise, the aspect of the window is lower than aspect of your region, so you should use the full width and scale up the vertical range by (aspect_region/aspect_viewport). Note that in both cases, the factor is >= 1.

In your code, you almost have implemented method 2, but you got the aspectRatio < 1 case wrong, it should be

   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);


来源:https://stackoverflow.com/questions/16498784/keeping-aspect-ratio-when-resizing-in-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!