removed timer rotation, now the user has full control,
added keyboard support, reset rotation with space
This commit is contained in:
		| @@ -24,7 +24,8 @@ public: | ||||
| protected: | ||||
| 	void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; | ||||
| 	void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE; | ||||
| 	void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; | ||||
| 	void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE; | ||||
| 	void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; | ||||
|  | ||||
| 	void initializeGL() Q_DECL_OVERRIDE; | ||||
| 	void resizeGL(int w, int h) Q_DECL_OVERRIDE; | ||||
| @@ -34,17 +35,17 @@ protected: | ||||
| 	void initTextures(); | ||||
|  | ||||
| private: | ||||
| 	QBasicTimer timer; | ||||
| 	struct { | ||||
| 		bool left = false; | ||||
| 		bool right = false; | ||||
| 		QVector2D position; | ||||
| 	} m_mouse; | ||||
| 	QOpenGLShaderProgram program; | ||||
| 	GeometryEngine *geometries; | ||||
|  | ||||
| 	QOpenGLTexture *texture; | ||||
|  | ||||
| 	QMatrix4x4 projection; | ||||
|  | ||||
| 	QVector2D mousePressPosition; | ||||
| 	QVector3D rotationAxis; | ||||
| 	qreal angularSpeed; | ||||
| 	QQuaternion rotation; | ||||
| 	QMatrix4x4 m_projection; | ||||
| 	QQuaternion m_rotation; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -2,13 +2,14 @@ | ||||
|  | ||||
| #include <QMouseEvent> | ||||
| #include <math.h> | ||||
| #include <iostream> | ||||
|  | ||||
| OglViewerWidget::OglViewerWidget(QWidget *parent) : | ||||
| 	QOpenGLWidget(parent), | ||||
| 	geometries(0), | ||||
| 	texture(0), | ||||
| 	angularSpeed(0) | ||||
| 	texture(0) | ||||
| { | ||||
| 	setFocus(); | ||||
| } | ||||
|  | ||||
| OglViewerWidget::~OglViewerWidget() | ||||
| @@ -24,45 +25,49 @@ OglViewerWidget::~OglViewerWidget() | ||||
| void OglViewerWidget::mousePressEvent(QMouseEvent *e) | ||||
| { | ||||
| 	// Save mouse press position | ||||
| 	mousePressPosition = QVector2D(e->localPos()); | ||||
| 	m_mouse.position = QVector2D(e->localPos()); | ||||
|  | ||||
| 	// Which button has been pressed? | ||||
| 	if (e->button() == Qt::LeftButton) | ||||
| 		m_mouse.left = true; | ||||
| 	else if (e->button() == Qt::RightButton) | ||||
| 		m_mouse.right = true; | ||||
| } | ||||
|  | ||||
| void OglViewerWidget::mouseReleaseEvent(QMouseEvent *e) | ||||
| { | ||||
| 	// Mouse release position - mouse press position | ||||
| 	QVector2D diff = QVector2D(e->localPos()) - 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; | ||||
| 	if (e->button() == Qt::LeftButton) | ||||
| 		m_mouse.left = false; | ||||
| 	else if (e->button() == Qt::RightButton) | ||||
| 		m_mouse.right = false; | ||||
| } | ||||
|  | ||||
| void OglViewerWidget::timerEvent(QTimerEvent *) | ||||
| void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) | ||||
| { | ||||
| 	// Decrease angular speed (friction) | ||||
| 	angularSpeed *= 0.99; | ||||
| 	if (m_mouse.left) | ||||
| 	{ | ||||
| 		// get the difference between last press and now | ||||
| 		QVector2D diff = QVector2D(e->localPos()) - m_mouse.position; | ||||
|  | ||||
| 	// Stop rotation when speed goes below threshold | ||||
| 	if (angularSpeed < 0.01) { | ||||
| 		angularSpeed = 0.0; | ||||
| 	} else { | ||||
| 		// Update rotation | ||||
| 		rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation; | ||||
| 		// update the new position | ||||
| 		m_mouse.position = QVector2D(e->localPos()); | ||||
|  | ||||
| 		// Request an update | ||||
| 		// calculate the rotation axis and rotate | ||||
| 		m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation; | ||||
|  | ||||
| 		// request an update | ||||
| 		update(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void OglViewerWidget::keyPressEvent(QKeyEvent *e) | ||||
| { | ||||
| 	if (e->key() == Qt::Key_Space) | ||||
| 		m_rotation = QQuaternion(); | ||||
|  | ||||
| 	update(); | ||||
| } | ||||
|  | ||||
| void OglViewerWidget::initializeGL() | ||||
| { | ||||
| 	initializeOpenGLFunctions(); | ||||
| @@ -80,8 +85,6 @@ void OglViewerWidget::initializeGL() | ||||
|  | ||||
| 	geometries = new GeometryEngine; | ||||
|  | ||||
| 	// Use QBasicTimer because its faster than QTimer | ||||
| 	timer.start(12, this); | ||||
| } | ||||
|  | ||||
| void OglViewerWidget::initShaders() | ||||
| @@ -128,10 +131,10 @@ void OglViewerWidget::resizeGL(int w, int h) | ||||
| 	const qreal zNear = 3.0, zFar = 7.0, fov = 45.0; | ||||
|  | ||||
| 	// Reset projection | ||||
| 	projection.setToIdentity(); | ||||
| 	m_projection.setToIdentity(); | ||||
|  | ||||
| 	// Set perspective projection | ||||
| 	projection.perspective(fov, aspect, zNear, zFar); | ||||
| 	m_projection.perspective(fov, aspect, zNear, zFar); | ||||
| } | ||||
|  | ||||
| void OglViewerWidget::paintGL() | ||||
| @@ -144,10 +147,10 @@ void OglViewerWidget::paintGL() | ||||
| 	// Calculate model view transformation | ||||
| 	QMatrix4x4 matrix; | ||||
| 	matrix.translate(0.0, 0.0, -5.0); | ||||
| 	matrix.rotate(rotation); | ||||
| 	matrix.rotate(m_rotation); | ||||
|  | ||||
| 	// Set modelview-projection matrix | ||||
| 	program.setUniformValue("mvp_matrix", projection * matrix); | ||||
| 	program.setUniformValue("mvp_matrix", m_projection * matrix); | ||||
|  | ||||
| 	// Use texture unit 0 which contains cube.png | ||||
| 	program.setUniformValue("texture", 0); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Anakin
					Anakin