...in paintGL. There is nothing saying the current program (or other state) cannot change between paintGL calls (or initializeGL and paintGL calls). Correctly call program.bind(). This eliminates the WebGL warning with WebAssembly. Pick-to: 6.5 6.4 Task-number: QTBUG-111304 Change-Id: I19792f5f193dcdb305473a939780df33deb1f8e1 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
169 lines
3.9 KiB
C++
169 lines
3.9 KiB
C++
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
|
|
#include "mainwidget.h"
|
|
|
|
#include <QMouseEvent>
|
|
|
|
#include <cmath>
|
|
|
|
MainWidget::~MainWidget()
|
|
{
|
|
// Make sure the context is current when deleting the texture
|
|
// and the buffers.
|
|
makeCurrent();
|
|
delete texture;
|
|
delete geometries;
|
|
doneCurrent();
|
|
}
|
|
|
|
//! [0]
|
|
void MainWidget::mousePressEvent(QMouseEvent *e)
|
|
{
|
|
// Save mouse press position
|
|
mousePressPosition = QVector2D(e->position());
|
|
}
|
|
|
|
void MainWidget::mouseReleaseEvent(QMouseEvent *e)
|
|
{
|
|
// Mouse release position - mouse press position
|
|
QVector2D diff = QVector2D(e->position()) - mousePressPosition;
|
|
|
|
// Rotation axis is perpendicular to the mouse position difference
|
|
// vector
|
|
QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized();
|
|
|
|
// Accelerate angular speed relative to the length of the mouse sweep
|
|
qreal acc = diff.length() / 100.0;
|
|
|
|
// Calculate new rotation axis as weighted sum
|
|
rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized();
|
|
|
|
// Increase angular speed
|
|
angularSpeed += acc;
|
|
}
|
|
//! [0]
|
|
|
|
//! [1]
|
|
void MainWidget::timerEvent(QTimerEvent *)
|
|
{
|
|
// Decrease angular speed (friction)
|
|
angularSpeed *= 0.99;
|
|
|
|
// Stop rotation when speed goes below threshold
|
|
if (angularSpeed < 0.01) {
|
|
angularSpeed = 0.0;
|
|
} else {
|
|
// Update rotation
|
|
rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation;
|
|
|
|
// Request an update
|
|
update();
|
|
}
|
|
}
|
|
//! [1]
|
|
|
|
void MainWidget::initializeGL()
|
|
{
|
|
initializeOpenGLFunctions();
|
|
|
|
glClearColor(0, 0, 0, 1);
|
|
|
|
initShaders();
|
|
initTextures();
|
|
|
|
//! [2]
|
|
// Enable depth buffer
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
// Enable back face culling
|
|
glEnable(GL_CULL_FACE);
|
|
//! [2]
|
|
|
|
geometries = new GeometryEngine;
|
|
|
|
// Use QBasicTimer because its faster than QTimer
|
|
timer.start(12, this);
|
|
}
|
|
|
|
//! [3]
|
|
void MainWidget::initShaders()
|
|
{
|
|
// Compile vertex shader
|
|
if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vshader.glsl"))
|
|
close();
|
|
|
|
// Compile fragment shader
|
|
if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fshader.glsl"))
|
|
close();
|
|
|
|
// Link shader pipeline
|
|
if (!program.link())
|
|
close();
|
|
|
|
// Bind shader pipeline for use
|
|
if (!program.bind())
|
|
close();
|
|
}
|
|
//! [3]
|
|
|
|
//! [4]
|
|
void MainWidget::initTextures()
|
|
{
|
|
// Load cube.png image
|
|
texture = new QOpenGLTexture(QImage(":/cube.png").mirrored());
|
|
|
|
// Set nearest filtering mode for texture minification
|
|
texture->setMinificationFilter(QOpenGLTexture::Nearest);
|
|
|
|
// Set bilinear filtering mode for texture magnification
|
|
texture->setMagnificationFilter(QOpenGLTexture::Linear);
|
|
|
|
// Wrap texture coordinates by repeating
|
|
// f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
|
|
texture->setWrapMode(QOpenGLTexture::Repeat);
|
|
}
|
|
//! [4]
|
|
|
|
//! [5]
|
|
void MainWidget::resizeGL(int w, int h)
|
|
{
|
|
// Calculate aspect ratio
|
|
qreal aspect = qreal(w) / qreal(h ? h : 1);
|
|
|
|
// Set near plane to 3.0, far plane to 7.0, field of view 45 degrees
|
|
const qreal zNear = 3.0, zFar = 7.0, fov = 45.0;
|
|
|
|
// Reset projection
|
|
projection.setToIdentity();
|
|
|
|
// Set perspective projection
|
|
projection.perspective(fov, aspect, zNear, zFar);
|
|
}
|
|
//! [5]
|
|
|
|
void MainWidget::paintGL()
|
|
{
|
|
// Clear color and depth buffer
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
texture->bind();
|
|
program.bind();
|
|
|
|
//! [6]
|
|
// Calculate model view transformation
|
|
QMatrix4x4 matrix;
|
|
matrix.translate(0.0, 0.0, -5.0);
|
|
matrix.rotate(rotation);
|
|
|
|
// Set modelview-projection matrix
|
|
program.setUniformValue("mvp_matrix", projection * matrix);
|
|
//! [6]
|
|
|
|
// Use texture unit 0 which contains cube.png
|
|
program.setUniformValue("texture", 0);
|
|
|
|
// Draw cube geometry
|
|
geometries->drawCubeGeometry(&program);
|
|
}
|