将QMatrix4x4与OpenGL功能结合使用

时间:2013-01-13 11:48:52

标签: qt opengl

是否有一种简单的方法可以将QMatrix4x4与OpenGL函数一起使用,特别是glMultMatrixf

如果我理解这一点,我必须转置矩阵,并确保转换qreal(可以是floatdouble,具体取决于底层系统)到GLfloat。 是不是有一个功能为我做这个?

QVector3D也遇到了同样的问题,我需要在函数GLfloat中将glVertex3fv数组作为{{1}}数组。

2 个答案:

答案 0 :(得分:4)

首先我想提一下QMatrix4x4有内置的矩阵乘法运算符(带有第二个矩阵,一个向量或一个标量)。但是,您的问题仍然需要答案,因为您希望迟早将矩阵传递给OpenGL。

QMatrix4x4使用qreals进行内部表示。虽然该类旨在直接与OpenGL一起使用(使用constData(),如Bart在他的回答中所建议的那样),如果你想保留平台,你可以确保将它传递给相应的OpenGL函数,具体取决于类型兼容性(在嵌入式设备上,qrealfloat!):

// these are defined in the OpenGL headers:
void glMultMatrixf(const GLfloat *m);
void glMultMatrixd(const GLdouble *m);

// add overloaded functions which call the underlying OpenGL function
inline void glMultMatrix(const GLfloat  *m) { glMultMatrixf(m); }
inline void glMultMatrix(const GLdouble *m) { glMultMatrixd(m); }

// add an overload for QMatrix4x4 for convenience
inline void glMultMatrix(const QMatrix4x4 &m) { glMultMatrix(m.constData()); }

您也可以将此机制用于向量,这里是glVertex*系列,由于“原始指针”重载需要考虑的组件数量,它更有意义,但是面向对象的重载可以做自动为你服务:

inline void glVertex2v(const GLfloat  *v) { glVertex2fv(v); }
inline void glVertex2v(const GLdouble *v) { glVertex2dv(v); }
inline void glVertex3v(const GLfloat  *v) { glVertex3fv(v); }
inline void glVertex3v(const GLdouble *v) { glVertex3dv(v); }
inline void glVertex4v(const GLfloat  *v) { glVertex4fv(v); }
inline void glVertex4v(const GLdouble *v) { glVertex4dv(v); }

// Note that QVectorND use floats, but we check this during compile time...
Q_STATIC_ASSERT(sizeof(QVector2D) == 2*sizeof(float));
Q_STATIC_ASSERT(sizeof(QVector3D) == 3*sizeof(float));
Q_STATIC_ASSERT(sizeof(QVector4D) == 4*sizeof(float));
inline void glVertex(const QVector2D &v) { glVertex2v(reinterpret_cast<const float*>(&v)); }
inline void glVertex(const QVector3D &v) { glVertex3v(reinterpret_cast<const float*>(&v)); }
inline void glVertex(const QVector4D &v) { glVertex4v(reinterpret_cast<const float*>(&v)); }

// Even for QPointF we can do it!
Q_STATIC_ASSERT(sizeof(QPointF) == 2*sizeof(qreal));
inline void glVertex(const QPointF &v) { glVertex4v(reinterpret_cast<const qreal*>(&v)); }

因此,如果进行了以下更改,您的代码将保持有效:

  • Qt更改QVector* / QMatrix的表示形式,分别使用浮点数/双打,
  • 您的代码更改了矢量的组件数

...尤其是当使用原始OpenGL命令(如glVertex3f

)时,第二种情况并非如此

上面代码中的Q_STATIC_ASSERT离子仅在Qt 5.0之后定义。如果您使用的是Qt4(或具有Qt4兼容性的代码),请在定义之前将其添加到某个全局头文件中:http://ideone.com/VDPUSg [来源:Qt5 / qglobal.h]

答案 1 :(得分:2)

除了ARM体系结构之外,

qreal被定义为所有平台上的双精度数。所以最有可能的是他们是双打。

那就是说,是的,您可以使用constData()方法将您的QMatrix4x4与OpenGL完美配合使用。当然,对于double类型,您必须使用glMultMatrixd,或者从中创建一个浮点矩阵。这可能不是你想要做的。 Qt有各种各样的例子,它们在OpenGL演示中使用矩阵类型。

我个人从不使用Qt的矩阵和矢量类型作为我的OpenGL代码(尽管我广泛使用Qt),而是选择像Eigen,GLM或其他合适的库。