I'm using QGlWidget to draw a couple of points. The problems I'm having is that I seem to fail to set up the perspective properly and establish correct view on the points. I must be misunderstanding the coordinates somewhere or doing something else stupid, but after reading a bunch of guides and tutotrials I'm still stuck. The screen is black, no points. Here's the code:
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);
}
I've tried manipulating z coordinate of the "eye" in gluLookAt to no avail, so I must be getting something else wrong.
To develop a more clear understanding of how gluPerspective()
and gluLookAt()
works, I recommend playing with the tutorials from Nate Robins , more specifically the projection demo.
Trust me, this is the droid you are looking for !
Anyway, a few days ago I wrote a spiced up version of Nehe lesson 5 (3D Shapes) in Qt:
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();
};
main.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();
}
I think what you've got there looks mostly correct, though your glViewport parameters look wrong. glViewport is supposed to be (left, bottom, width, height), but you're using something else.
Set glViewport to glViewport(0,0,width,height);
.
For more explanation:
After transformation by modelViewProjection matrix (and perspective divide), all coordinates lie in what's known as Normalized Device Coordinates (abbreviated as NDC). NDC ranges from -1 to 1 on each axis, which puts (0,0,0) right in the center of the viewing region.
When your point lies directly in front of the camera, this gets transformed to xy (0,0) in normalized device coordinates.
If you look at the formulas on glViewport, these map NDC to the actual pixels on the screen.
So if you supply (0,0,1024,768)
as the parameters, it gets mapped as the following:
screen X = ( Xnd + 1 ) ( width / 2) + x;
screen Y = ( Ynd + 1 ) ( height / 2) + y;
Substituting our glViewport values:
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
Your near value is quite large to be honest, usually this has to be a low value so that if you have a 2D environment as your example you can still render objects. I would say a 0.1(0.5)
for the near value of the perspective should go nicely.
Note: If you set the near value to be a big number your geometry will be clipped by the camera (perspective frustum).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.