This is not a Qt question but i'm using the framework.
This is definitely not an OpenGL question but a more general question about perspective rendering. Someone who knows their OpenGL could certainly help.

I am trying to understand the graphical pipeline rendering model and have a test program to show my progress.
This demonstration tries to draw a wireframe cube using a perspective view. There is a DEFINE in the code which you can turn the perspective transform step on and off.
The cube and colored axes are clearly visible when the define is missing, but the perspective transform doesn't do what I expect when I turn it on.

Some numerical values that I question are ViewTransform distance (i.e. the camera), PerspectiveTransform field-of-view, PerspectiveTransform near and far planes.
My understanding of pipeline order may also be wrong, but I think I've got that.

Are my parameter values just wrong or am I missing something else?
Is there a scaling to a unit cube that I need before applying the PerspectiveTransform?

Qt Code:
  1. #include <QApplication>
  2. #include <QWidget>
  3. #include <QVector3D>
  4. #include <QMatrix4x4>
  5. #include <QPainter>
  6. #include <QResizeEvent>
  7. #include <QPaintEvent>
  8.  
  9. class Widget : public QWidget
  10. {
  11. Q_OBJECT
  12. public:
  13. explicit Widget(QWidget* parent = NULL);
  14. virtual ~Widget();
  15.  
  16. protected:
  17. void paintEvent(QPaintEvent* event);
  18. void resizeEvent(QResizeEvent* event);
  19.  
  20. void DrawLine(QPainter& painter, const QMatrix4x4& transform, QVector3D vector1, QVector3D vector2);
  21. void PaintCube(QPainter& painter, const QMatrix4x4& transform);
  22. void PaintAxes(QPainter& painter, const QMatrix4x4& transform);
  23.  
  24. void UpdateViewTransform();
  25. void UpdateProjectionTransform(const QSize& newSize);
  26. void UpdateModelTransform();
  27. void UpdateTranslateTransform(const QSize& newSize);
  28.  
  29. QMatrix4x4 TranslateTransform;
  30. QMatrix4x4 ProjectionTransform;
  31. QMatrix4x4 ViewTransform;
  32. QMatrix4x4 ModelTransform;
  33. };
  34.  
  35. #define WITH_PERSPECTIVE_PROJECTION
  36.  
  37. namespace
  38. {
  39. QVector3D TOP_LEFT_FRONT( -100.0, 100.0, 100.0 );
  40. QVector3D TOP_RIGHT_FRONT( 100.0, 100.0, 100.0 );
  41. QVector3D BOTTOM_RIGHT_FRONT( 100.0, -100.0, 100.0 );
  42. QVector3D BOTTOM_LEFT_FRONT( -100.0, -100.0, 100.0 );
  43. QVector3D TOP_LEFT_BACK( -100.0, 100.0, -100.0 );
  44. QVector3D TOP_RIGHT_BACK( 100.0, 100.0, -100.0 );
  45. QVector3D BOTTOM_RIGHT_BACK( 100.0, -100.0, -100.0 );
  46. QVector3D BOTTOM_LEFT_BACK( -100.0, -100.0, -100.0 );
  47. QVector3D X_AXIS( 200, 0, 0 );
  48. QVector3D Y_AXIS( 0, 200, 0 );
  49. QVector3D Z_AXIS( 0, 0, 200 );
  50. }
  51.  
  52. Widget::Widget(QWidget* parent)
  53. : QWidget(parent)
  54. {
  55. UpdateViewTransform();
  56. UpdateModelTransform();
  57. }
  58.  
  59. Widget::~Widget()
  60. {
  61. }
  62.  
  63. void Widget::resizeEvent(QResizeEvent* event)
  64. {
  65. UpdateTranslateTransform(event->size());
  66. UpdateProjectionTransform(event->size());
  67. QWidget::resizeEvent(event);
  68. }
  69.  
  70. void Widget::UpdateTranslateTransform(const QSize& newSize)
  71. {
  72. TranslateTransform.setToIdentity();
  73. TranslateTransform.translate(newSize.width() / 2 , newSize.height() / 2);
  74. }
  75.  
  76. void Widget::UpdateViewTransform()
  77. {
  78. // I question the camera distance compared to the perspective settings
  79. ViewTransform.lookAt(QVector3D(0, 0, 300), QVector3D(), QVector3D(0, 1, 0));
  80. }
  81.  
  82. void Widget::UpdateProjectionTransform(const QSize& newSize)
  83. {
  84. // I question the fov angle, near plane, and far plane settings compared to the camera position
  85. ProjectionTransform.perspective(120.0, newSize.width() / newSize.height(), 1, 300.0);
  86. }
  87.  
  88. void Widget::UpdateModelTransform()
  89. {
  90. ModelTransform.setToIdentity(); // no need to move the object around yet.
  91. }
  92.  
  93. void Widget::paintEvent(QPaintEvent* event)
  94. {
  95. Q_UNUSED(event);
  96.  
  97. QPainter painter(this);
  98.  
  99. QMatrix4x4 transform;
  100. transform *= TranslateTransform;
  101. #ifdef WITH_PERSPECTIVE_PROJECTION
  102. transform *= ProjectionTransform;
  103. #endif
  104. transform *= ViewTransform.inverted();
  105. transform *= ModelTransform;
  106.  
  107. PaintCube(painter, transform);
  108. PaintAxes(painter, transform);
  109. }
  110.  
  111. void Widget::PaintCube(QPainter& painter, const QMatrix4x4& transform)
  112. {
  113. painter.setPen(Qt::black);
  114. DrawLine(painter, transform, TOP_LEFT_FRONT, TOP_RIGHT_FRONT);
  115. DrawLine(painter, transform, TOP_RIGHT_FRONT, BOTTOM_RIGHT_FRONT);
  116. DrawLine(painter, transform, BOTTOM_RIGHT_FRONT, BOTTOM_LEFT_FRONT);
  117. DrawLine(painter, transform, BOTTOM_LEFT_FRONT, TOP_LEFT_FRONT);
  118. DrawLine(painter, transform, TOP_LEFT_BACK, TOP_RIGHT_BACK);
  119. DrawLine(painter, transform, TOP_RIGHT_BACK, BOTTOM_RIGHT_BACK);
  120. DrawLine(painter, transform, BOTTOM_RIGHT_BACK, BOTTOM_LEFT_BACK);
  121. DrawLine(painter, transform, BOTTOM_LEFT_BACK, TOP_LEFT_BACK);
  122. DrawLine(painter, transform, TOP_LEFT_FRONT, TOP_LEFT_BACK);
  123. DrawLine(painter, transform, TOP_RIGHT_FRONT, TOP_RIGHT_BACK);
  124. DrawLine(painter, transform, BOTTOM_RIGHT_FRONT, BOTTOM_RIGHT_BACK);
  125. DrawLine(painter, transform, BOTTOM_LEFT_FRONT, BOTTOM_LEFT_BACK);
  126. }
  127.  
  128. void Widget::PaintAxes(QPainter& painter, const QMatrix4x4& transform)
  129. {
  130. painter.setPen(Qt::red);
  131. DrawLine(painter, transform, QVector3D(), X_AXIS);
  132. painter.setPen(Qt::green);
  133. DrawLine(painter, transform, QVector3D(), Y_AXIS);
  134. painter.setPen(Qt::blue);
  135. DrawLine(painter, transform, QVector3D(), Z_AXIS);
  136. }
  137.  
  138. void Widget::DrawLine(QPainter& painter, const QMatrix4x4& transform, QVector3D vector1, QVector3D vector2)
  139. {
  140. vector1 = transform.map(vector1);
  141. vector2 = transform.map(vector2);
  142. painter.drawLine(vector1.toPointF(), vector2.toPointF());
  143. }
  144.  
  145. int main(int argc, char *argv[])
  146. {
  147. QApplication a(argc, argv);
  148. Widget w;
  149. w.resize(800, 600);
  150. w.show();
  151. return a.exec();
  152. }
  153.  
  154. #include "main.moc"
To copy to clipboard, switch view to plain text mode