我正在尝试将一个多维数据集呈现到QSplitter中的QGLWidgetput中。我希望它具有1:1的比例,所以它是一个立方体,无论窗口尺寸如何,都保持该比例。不过,我还无法使它正常工作。不管我做什么,立方体都会随着窗口伸展。
代码的工作方式还有另外两个问题。matrix.setToIdentity()
重置除投影和转换(发生在initializeGL()
末尾)以外的所有内容,因此,当我在resizeGL()
中调用它时,投影将与前一个结合,即使我在此之前将矩阵设置为恒等。aspect ratio
的参数matrix.perspective()
似乎没有任何作用。我尝试了多个值,但没有效果。
由于某种原因,投影是正交的,而不是透视的。
矩阵仍然是perspective()
之后的标识,但是仅当我按setToIdentity()
顺序在perspective()
中调用resizeGL
和initializeGL()
时才可以。resizeGL()
和translate()
中的矩阵运算得到不同的处理。如果我没有在perspective()
中调用initializeGL()
和resizeGL()
,则即使稍后在QMatrix4x4
中进行操作,该多维数据集也不会出现。
有人可以向我解释吗?我以为类是用于将矩阵转换为3D的,因此我不必自己实现它们。
我看过一些教程,但是它们要么以类似的方式使用某种矩阵,要么似乎使用了已弃用的OpenGL函数。尝试将宽度和高度转换为浮点,并使用单独的矩阵进行转换。
如何使1:1比例起作用?
我的代码的相关部分:
void ModelView::initializeGL()
{
m_program = new QGLShaderProgram(this);
m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentShaderSource);
m_program->link();
GLuint shader_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shader_id, 1, vertexShaderSource, NULL);
glCompileShader(shader_id);
ShaderIds[2] = shader_id;
shader_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(shader_id, 1, fragmentShaderSource, NULL);
glCompileShader(shader_id);
ShaderIds[1] = shader_id;
glAttachShader(ShaderIds[0], ShaderIds[1]);
glAttachShader(ShaderIds[0], ShaderIds[2]);
glLinkProgram(ShaderIds[0]);*/
matrix.setToIdentity(); //--------------------------------------
float aspect = (((float)width())/((float)height()));
matrix.perspective(60, aspect, 0.1, 100.0);
matrix.translate(0, 0, -2);
}
void ModelView::paintGL()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(.5f, .5f, .5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width(), height());
m_program->bind();
m_posAttr = m_program->attributeLocation("posAttr");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
m_program->setUniformValue(m_matrixUniform, matrix); //-----------------
glGenBuffers(1, &BufferId);
glGenBuffers(1, &IndexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, BufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId);
glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, VertexSize, 0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid *)RgbOffset);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
void ModelView::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
matrix.setToIdentity(); //------------------------------------
matrix.translate(0, 0, -2);
matrix.perspective(60, ((float)w)/((float)h), 0.1, 100.0);
updateGL();
}
最佳答案
终于发现出了什么问题。
首先,矩阵运算不应该在initializeGL()
中。不确定原因。正确的位置(在考虑范围之内)在resizeGL()
中,因为它在第一个帧渲染的某个地方被调用。
其次,矩阵乘法有其定义的顺序,类似于透视>平移>旋转。否则会拧紧。
因此,resizeGL()
中正确(或至少有效)的代码如下所示:
glViewport(startX, startY, width, height); //resize the viewport
matrix.setToIdentity(); //reset the uniform value (matrix)
perspectiveMatrix.setToIdentity(); //reset the projection matrix
//set new projection (aspect ratio)
perspectiveMatrix.perspective(angle, (float)width/(float)height, nearPlane, farPlane);
matrix *= perspectiveMatrix; //apply transformations
matrix *= translationMatrix;
matrix *= rotationMatrix;
updateGL(); //re-render