2

我正在使用 QGlWidget 来绘制几个点。我遇到的问题是我似乎无法正确设置视角并建立正确的观点。我一定是在某个地方误解了坐标或者做了其他愚蠢的事情,但是在阅读了一堆指南和教程后,我仍然被卡住了。屏幕是黑的,没有点。这是代码:

 void CGLWidget::initializeGL()
 {
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_ALPHA_TEST);
    glDisable(GL_BLEND);
    glEnable(GL_POINT_SPRITE);
    glClearColor(0, 0, 0, 1);
    assert (glGetError() == GL_NO_ERROR);
 }

void CGLWidget::resizeGL(int w, int h)
 {
    glViewport(-w/2, -h/2, w/2, h <= 0 ? 1 : h/2);

    glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective
    //Set the camera perspective
    glLoadIdentity(); //Reset the camera
    gluPerspective(80.0,   //The camera FoV
    w/(double)h, //The width-to-height ratio
    1,                   //The near z clipping coordinate
    100);                //The far z clipping coordinate
 }

 void CGLWidget::paintGL()
 {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
    glLoadIdentity();

    glColor3i(255, 255, 255);
    glBegin(GL_POINTS);
        glVertex3d(0,0, -2);
        glVertex3d(0,0, -3);
        glVertex3d(0,0, +3);
        glVertex3d(0,0, 0);
        glVertex3f(-0.75f, -0.25f, -5.0f);
    glEnd();

    assert (glGetError() == GL_NO_ERROR);
 }

我已经尝试在 gluLookAt 中操纵“眼睛”的 z 坐标但无济于事,所以我一定是弄错了。

4

3 回答 3

3

为了更清楚地了解如何gluPerspective()和工作,我建议使用Nate RobinsgluLookAt()的教程,更具体地说是投影演示。

相信我,这就是你要找的机器人

在此处输入图像描述

无论如何,几天前我在 Qt 中写了 Nehe 第5 课(3D 形状)的增强版:

GLWidget.cpp

#include "GLWidget.h"

#include <iostream>
#include <QKeyEvent>
#include <QTimer>

GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent)
{
    angle_tri = 0.f;
    angle_quad = 0.f;
    _eye_x = 0.f;
    _eye_y = 0.f;
    _mouse_is_moving = false;
    _width = 0;
    _height = 0;
}

GLWidget::~GLWidget()
{

}

void GLWidget::_tick()
{
    update(); // triggers paintGL()
    QTimer::singleShot(33, this, SLOT(_tick()));
}

void GLWidget::initializeGL()
{
//    glShadeModel(GL_SMOOTH);                          // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);               // Black Background
//    glClearDepth(1.0f);                                   // Depth Buffer Setup
//    glEnable(GL_DEPTH_TEST);                          // Enables Depth Testing
//    glDepthFunc(GL_LEQUAL);                               // The Type Of Depth Testing To Do
//    glEnable ( GL_COLOR_MATERIAL );
//    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    _tick();
}

void GLWidget::paintGL()
{    
    if (_mouse_is_moving)
    {
        glMatrixMode   ( GL_PROJECTION );  // Select The Projection Matrix
        glLoadIdentity ( );                // Reset The Projection Matrix

        gluPerspective ( 60, ( float ) _width / ( float ) _height, 1.0, 50.0 );
        gluLookAt(0.0,  0.0, 2.0,           // eye
                  _eye_x,  _eye_y, 0.0,     // center
                  0.0,  1.0, 0.0);          // up

        std::cout << "paintGL: eye " << _eye_x << "," << _eye_y << std::endl;

    }

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

    glMatrixMode   ( GL_MODELVIEW );  // Select The Model View Matrix
    glLoadIdentity();                                   // Reset The Current Modelview Matrix

    glPushMatrix();
    glTranslatef(-1.5f,0.0f,-6.0f);                     // Move Left 1.5 Units And Into The Screen 6.0
    glRotatef(angle_tri,0.0f,1.0f,0.0f);                // Rotate The Triangle On The Y axis
    glBegin(GL_TRIANGLES);                              // Drawing Using Triangles
        glColor3f(1.0f,0.0f,0.0f);          // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);          // Top Of Triangle (Front)
        glColor3f(0.0f,1.0f,0.0f);          // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);          // Left Of Triangle (Front)
        glColor3f(0.0f,0.0f,1.0f);          // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);          // Right Of Triangle (Front)

        glColor3f(1.0f,0.0f,0.0f);          // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);          // Top Of Triangle (Right)
        glColor3f(0.0f,0.0f,1.0f);          // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);          // Left Of Triangle (Right)
        glColor3f(0.0f,1.0f,0.0f);          // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);         // Right Of Triangle (Right)

        glColor3f(1.0f,0.0f,0.0f);          // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);          // Top Of Triangle (Back)
        glColor3f(0.0f,1.0f,0.0f);          // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);         // Left Of Triangle (Back)
        glColor3f(0.0f,0.0f,1.0f);          // Blue
        glVertex3f(-1.0f,-1.0f, -1.0f);         // Right Of Triangle (Back)

        glColor3f(1.0f,0.0f,0.0f);          // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);          // Top Of Triangle (Left)
        glColor3f(0.0f,0.0f,1.0f);          // Blue
        glVertex3f(-1.0f,-1.0f,-1.0f);          // Left Of Triangle (Left)
        glColor3f(0.0f,1.0f,0.0f);          // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);          // Right Of Triangle (Left)
    glEnd();                                            // Finished Drawing The Triangle

    glLoadIdentity();                   // Reset The Current Modelview Matrix
    glTranslatef(1.5f,0.0f,-9.0f);              // Move Right 1.5 Units And Into The Screen 6.0
    glRotatef(angle_quad,1.0f,0.0f,0.0f);           // Rotate The Quad On The X axis
    glBegin(GL_QUADS);                                  // Draw A Quad
        glColor3f(0.0f,1.0f,0.0f);          // Set The Color To Green
        glVertex3f( 1.0f, 1.0f,-1.0f);          // Top Right Of The Quad (Top)
        glVertex3f(-1.0f, 1.0f,-1.0f);          // Top Left Of The Quad (Top)
        glVertex3f(-1.0f, 1.0f, 1.0f);          // Bottom Left Of The Quad (Top)
        glVertex3f( 1.0f, 1.0f, 1.0f);          // Bottom Right Of The Quad (Top)

        glColor3f(1.0f,0.5f,0.0f);          // Set The Color To Orange
        glVertex3f( 1.0f,-1.0f, 1.0f);          // Top Right Of The Quad (Bottom)
        glVertex3f(-1.0f,-1.0f, 1.0f);          // Top Left Of The Quad (Bottom)
        glVertex3f(-1.0f,-1.0f,-1.0f);          // Bottom Left Of The Quad (Bottom)
        glVertex3f( 1.0f,-1.0f,-1.0f);          // Bottom Right Of The Quad (Bottom)

        glColor3f(1.0f,0.0f,0.0f);          // Set The Color To Red
        glVertex3f( 1.0f, 1.0f, 1.0f);          // Top Right Of The Quad (Front)
        glVertex3f(-1.0f, 1.0f, 1.0f);          // Top Left Of The Quad (Front)
        glVertex3f(-1.0f,-1.0f, 1.0f);          // Bottom Left Of The Quad (Front)
        glVertex3f( 1.0f,-1.0f, 1.0f);          // Bottom Right Of The Quad (Front)

        glColor3f(1.0f,1.0f,0.0f);          // Set The Color To Yellow
        glVertex3f( 1.0f,-1.0f,-1.0f);          // Bottom Left Of The Quad (Back)
        glVertex3f(-1.0f,-1.0f,-1.0f);          // Bottom Right Of The Quad (Back)
        glVertex3f(-1.0f, 1.0f,-1.0f);          // Top Right Of The Quad (Back)
        glVertex3f( 1.0f, 1.0f,-1.0f);          // Top Left Of The Quad (Back)

        glColor3f(0.0f,0.0f,1.0f);          // Set The Color To Blue
        glVertex3f(-1.0f, 1.0f, 1.0f);          // Top Right Of The Quad (Left)
        glVertex3f(-1.0f, 1.0f,-1.0f);          // Top Left Of The Quad (Left)
        glVertex3f(-1.0f,-1.0f,-1.0f);          // Bottom Left Of The Quad (Left)
        glVertex3f(-1.0f,-1.0f, 1.0f);          // Bottom Right Of The Quad (Left)

        glColor3f(1.0f,0.0f,1.0f);          // Set The Color To Violet
        glVertex3f( 1.0f, 1.0f,-1.0f);          // Top Right Of The Quad (Right)
        glVertex3f( 1.0f, 1.0f, 1.0f);          // Top Left Of The Quad (Right)
        glVertex3f( 1.0f,-1.0f, 1.0f);          // Bottom Left Of The Quad (Right)
        glVertex3f( 1.0f,-1.0f,-1.0f);          // Bottom Right Of The Quad (Right)
    glEnd();                                            // Done Drawing The Quad
    glPopMatrix();

    angle_tri += 3.2f;                      // Increase The Rotation Variable For The Triangle ( NEW )
    angle_quad -= 3.15f;                    // Decrease The Rotation Variable For The Quad     ( NEW )

}

void GLWidget::resizeGL( int w, int h)
{
    _width = w;
    _height = h;
    glViewport     ( 0, 0, w, h );
    glMatrixMode   ( GL_PROJECTION );  // Select The Projection Matrix
    glLoadIdentity ( );                // Reset The Projection Matrix
    if ( h==0 )  // Calculate The Aspect Ratio Of The Window
       gluPerspective ( 60, ( float ) w, 1.0, 50.0 );
    else
       gluPerspective ( 60, ( float ) w / ( float ) h, 1.0, 50.0 );

    gluLookAt(0.0,  0.0, 2.0,   // eye
              0.0,  0.0, 0.0,   // center
              0.0,  1.0, 0.0);  // up

    glMatrixMode   ( GL_MODELVIEW );  // Select The Model View Matrix
    glLoadIdentity ( );    // Reset The Model View Matrix
}

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    std::cout << "mousePressEvent:" << std::endl;
    _mouse_is_moving = true;
}

void GLWidget::mouseReleaseEvent(QMouseEvent *event)
{
    std::cout << "mouseReleaseEvent:" << std::endl;
    _mouse_is_moving = false;
}

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (_mouse_x == 0)
        _mouse_x = event->pos().x();

    if (_mouse_y == 0)
        _mouse_y = event->pos().y();

    std::cout << "mouseMoveEvent: " << event->pos().x() << "," << event->pos().y() << std::endl;

    if (event->pos().x() > _mouse_x)
    {
        _eye_x += 0.10;
    }
    else if (event->pos().x() < _mouse_x)
    {
        _eye_x -= 0.10;
    }

    if (event->pos().y() > _mouse_y)
    {
        _eye_y += 0.10;
    }
    else if (event->pos().y() < _mouse_y)
    {
        _eye_y -= 0.10;
    }

    _mouse_x = event->pos().x();
    _mouse_y = event->pos().y();
}

GLWidget.h

#include <QGLWidget>

class GLWidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit GLWidget(QWidget* parent = 0);
    virtual ~GLWidget();

    /* OpenGL initialization, viewport resizing, and painting */

    void initializeGL();

    void paintGL();

    void resizeGL( int width, int height);

    /* enable the user to interact directly with the scene using the mouse */

    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);    
    void mouseMoveEvent(QMouseEvent *event);

private:
    float angle_tri;            // Angle For The Triangle
    float angle_quad;           // Angle For The Quad
    float _eye_x;
    float _eye_y;
    bool _mouse_is_moving;
    int _mouse_x;
    int _mouse_y;
    int _width;
    int _height;

protected slots:
    void _tick();

};

主.cpp

#include <QApplication>
#include "glwidget.h"

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    GLWidget gl_widget;
    gl_widget.show();

    return app.exec();
}

在此处输入图像描述

于 2012-09-17T19:28:52.353 回答
2

我认为你在那里得到的东西看起来大多是正确的,尽管你的 glViewport 参数看起来是错误的。glViewport 应该是(左,下,宽,高),但你使用的是别的东西。

将 glViewport 设置为glViewport(0,0,width,height);.

更多解释:

通过 modelViewProjection 矩阵(和透视分割)进行转换后,所有坐标都位于所谓的标准化设备坐标(缩写为 NDC)中。NDC 在每个轴上的范围从 -1 到 1,这将 (0,0,0) 放在查看区域的中心。

当您的点直接位于相机前面时,它会转换为标准化设备坐标中的 xy (0,0)。

如果您查看 glViewport 上的公式,这些公式会将 NDC 映射到屏幕上的实际像素。

因此,如果您提供(0,0,1024,768)参数,它会被映射如下:

screen X = ( Xnd + 1 ) ( width / 2) + x;
screen Y = ( Ynd + 1 ) ( height / 2) + y;

替换我们的 glViewport 值:

screen X = ( 0 + 1 ) ( 1024 / 2) + 0;
screen Y = ( 0 + 1 ) ( 768  / 2) + 0;

screen X = ( 1 ) ( 1024 / 2) ;
screen Y = ( 1 ) ( 768  / 2) ;

screen X = ( 1 ) ( 512 ) ;
screen Y = ( 1 ) ( 384 ) ;

screen X =  512 ; //center of screen X
screen Y =  384 ; //center of screen Y
于 2012-09-17T19:27:56.290 回答
-1

老实说,您的 near 值非常大,通常这必须是一个较低的值,这样如果您有一个 2D 环境作为示例,您仍然可以渲染对象。我会说0.1(0.5)视角的近值应该很好。

注意:如果您将 near 值设置为较大的数字,您的几何体将被相机裁剪(透视平截头体)。

于 2012-09-17T19:23:59.070 回答