3

2D レンダリングに Qt + OpenGl を使用しています。私は OpenGL の初心者であり、一生このアスペクト比の問題を理解できません。glOrtho と gViewPort を理解していると思うたびに、次回は別の問題に直面します。座標が-1と1の間のように対称である場合、私のコードは機能しますが、そうでない場合は機能しません。これらを一度は乗り越えたいと思っています。私が検索して適用したすべての提案は、私にとって無駄になりました。

私の問題声明:

私は正方形と三角形をレンダリングしており、キーストローク「R」でそれらを切り替えます。私もズームインとズームアウトしています。正方形はアスペクト比を維持していますが、三角形はそうではありません。形状の座標は次のとおりです。

正方形: (-10, -250), (500, -250), (500, -260), (-10, -260);

三角形: (250, 0)、(310, 0)、(280, 30)

基本的に三角形の上はレンダリングできません。同じコードは次のとおりです。

マイコード

#include <QtGui/QMouseEvent>
#include <qdebug.h>
#include "GLWidget.h"
#include "stdio.h"
#include "qgl.h"
#include "qimage.h"

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{
    setMouseTracking(true);
}

void GLWidget::initializeGL()
{
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_COLOR_MATERIAL);
    glEnable(GL_BLEND);
    glEnable(GL_POLYGON_SMOOTH);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(1, 1, 1, 0);
    glEnable( GL_POINT_SMOOTH ); // For Circular Points
}

void GLWidget::resizeGL(int w, int h)
{
    canvas_width = (double)w;
    canvas_height = (double)h;
    aspect_ratio = canvas_width/canvas_height;

    left_plane  = 250;
    right_plane = 310;
    bottom_plane  = 0;
    top_plane  = 60;
    z_near_plane = 1;
    z_far_plane  = -1;

    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    if( canvas_width > canvas_height ){ 
        glOrtho(left_plane*aspect_ratio, right_plane*aspect_ratio, bottom_plane, top_plane, z_near_plane, z_far_plane);
    }else{
        glOrtho(left_plane, right_plane, bottom_plane/aspect_ratio, top_plane/aspect_ratio, z_near_plane, z_far_plane);
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1,0,0); // red

    glBegin(GL_POLYGON);
        //glVertex2f(-30,0);
        //glVertex2f(30,0);
        //glVertex2f(0,60);
        glVertex2f(250,0);
        glVertex2f(310,0);
        glVertex2f(280,60);
    glEnd();
}

left_plane*aspect_ratio が描画をクリップするため、トレイングルは表示されません (250 が最小 X、250*1.4 > 310、310 が最大 X)。

私は自分自身を明確にしたことを願っています。

画像も配置しようと思います (画像を他のサイトにアップロードしてここにリンクする必要があると思いますか?)。

4

1 に答える 1

1

あなたの問題は、境界ボックス (左/右/上/下平面に割り当てられた値) がビューポートと同じ縦横比を持っていないことです。オブジェクトのバウンディング ボックスがある場合は、正しい縦横比 (w/h) のビューポート座標を見つける必要があります。ビューポートは、バウンディング ボックスの中心に配置され、バウンディング ボックスに収まる大きさである必要があります。ただし、ビューポートの縦横比は境界ボックスのサイズとは関係ありません。

一般に、3D バウンディング ボックス (8 つのコーナー ポイント) があります。各コーナーを画面に投影し、最小/最大を使用して、画面の中央に配置する必要がある長方形を取得します。次に、ビューポートのアスペクト比 a=w/r に対して、その長方形のアスペクト比 ar = wr/hr を確認します。a < ar の場合、wr を w に合わせる必要があります。それ以外の場合は、hr を h に合わせます。

void GLWidget::resizeGL(int w, int h)
{
  // First set up the projection.
  double canvas_width = (double)w;
  double canvas_height = (double)h;
  double a = canvas_width / canvas_height;

  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-a, +a, -1, +1, -1, +1);

  // Now set up the view matrix.
  double leftBoundingRectangle  = 250;
  double rightBoundingRectangle = 310;
  double bottomBoundingRectangle  = 0;
  double topBoundingRectangle  = 60;

  double widthBoundingRectangle = rightBoundingRectangle - leftBoundingRectangle;
  double heightBoundingRectangle = topBoundingRectangle - bottomBoundingRectangle;

  double ar = widthBoundingRectangle / heightBoundingRectangle;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  // Center on bounding rectangle center.
  double tx = (leftBoundingRectangle + rightBoundingRectangle)/2.0, ty = (topBoundingRectangle + bottomBoundingRectangle)/2.0;
  glTranslated(tx, ty, 0.0); // or is it -tx, -ty?

  // Scale to fit bounding box.
  double s;
  if (ar > a)
  {
    s = ... // sorry, but you have to figure this one out for yourself. :)
  }
  else
  {
    s = ...
  }
  glScaled(s,s,s);
}
于 2013-05-01T16:28:08.363 に答える