Skip to content
Snippets Groups Projects
Select Git revision
  • 4c177f2ddc28dd2733ce17e664ceb745c022330c
  • master default protected
  • developement_1 protected
  • Version_1.2.4
  • Version_1.2.3
  • Version_1.2.2
  • Version_1.2.1
  • Version_1.2.0
  • Version_1.0.1
  • Version_1.0.0
  • Version_0.1.0
  • Version_0.0.6
  • Version_0.0.5
  • Version_0.0.4
  • Version_0.0.3
  • Version_0.0.2
  • Version_0.0.1
17 results

OglViewerWidget.cpp

  • user avatar
    Anakin authored
    bugs:
    - background cannot be changed during runtime
    4c177f2d
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    OglViewerWidget.cpp 8.05 KiB
    #include "..\Header\OglViewerWidget.h"
    #include "..\Header\MainWindow.h"
    #include <QMouseEvent>
    #include <QDropEvent>
    #include <QMimeData>
    #include <math.h>
    #include <iostream>
    
    #define DEFAULT_Z_DISTANCE -4.0
    
    
    /////////////////////////////////////////////////////////////////////////
    // public constructor/destructor
    
    OglViewerWidget::OglViewerWidget(QWidget *parent) :
    	QOpenGLWidget(parent),
    	m_dataEngine(0)
    {
    	setFocus();
    	m_translation.setZ(DEFAULT_Z_DISTANCE);
    	setAcceptDrops(true);
    
    }
    
    OglViewerWidget::~OglViewerWidget()
    {
    	// Make sure the context is current when deleting the texture
    	// and the buffers.
    	makeCurrent();
    	delete m_dataEngine;
    	doneCurrent();
    }
    
    
    /////////////////////////////////////////////////////////////////////////
    // protected functions
    
    void OglViewerWidget::mousePressEvent(QMouseEvent *e)
    {
    	// Save mouse press position
    	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)
    {
    	if (e->button() == Qt::LeftButton)
    		m_mouse.left = false;
    	else if (e->button() == Qt::RightButton)
    		m_mouse.right = false;
    }
    
    void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
    {
    	if (m_mouse.left)
    	{
    		// get the difference between last press and now
    		QVector2D diff = QVector2D(e->localPos()) - m_mouse.position;
    
    		// update the new position
    		m_mouse.position = QVector2D(e->localPos());
    
    		// calculate the rotation axis and rotate
    		if (m_rotDirections.x && m_rotDirections.y && m_rotDirections.z)
    		{
    			m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation;
    		}
    		else if (m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z)
    		{
    
    			float pitch, yaw, roll;
    			m_rotation.getEulerAngles(&pitch, &yaw, &roll);
    
    			pitch += diff.y() * 0.5;
    			yaw += diff.x() * 0.5;
    
    			if (pitch > 89)
    				pitch = 89;
    			else if (pitch < -89)
    				pitch = -89;
    
    			m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
    
    		}
    		else if (m_rotDirections.x && !m_rotDirections.y && !m_rotDirections.z)
    		{
    			m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0).normalized(), diff.x() * 0.5) * m_rotation;
    		}
    		else if (!m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z)
    		{
    			m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0).normalized(), diff.y() * 0.5) * m_rotation;
    		}
    		else if (!m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z)
    		{
    			m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 0.0, 1.0).normalized(), diff.x() * 0.5) * m_rotation;
    		}
    		else if (m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z)
    		{
    			float pitch, yaw, roll;
    			m_rotation.getEulerAngles(&pitch, &yaw, &roll);
    			roll -= diff.y() * 0.5;
    			yaw += diff.x() * 0.5;
    
    			m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
    		}
    		else if (!m_rotDirections.x && m_rotDirections.y && m_rotDirections.z)
    		{
    			float pitch, yaw, roll;
    			m_rotation.getEulerAngles(&pitch, &yaw, &roll);
    			pitch += diff.y() * 0.5;
    			roll += diff.x() * 0.5;
    
    			if (pitch > 89)
    				pitch = 89;
    			else if (pitch < -89)
    				pitch = -89;
    
    			m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
    		}
    
    		
    		// request an update
    		update();
    	}
    	else if (m_mouse.right)
    	{
    		// get the difference between last press and now
    		QVector2D diff = QVector2D(e->localPos()) - m_mouse.position;
    
    		// update the new position
    		m_mouse.position = QVector2D(e->localPos());
    
    		// calculate the translation
    		m_translation += {(float)(diff.x() * 0.01), (float)(diff.y() * -0.01), 0.0};
    
    		// request an update
    		update();
    	}
    }
    
    void OglViewerWidget::wheelEvent(QWheelEvent *e)
    {
    	m_translation += {0.0, 0.0, (float)e->angleDelta().y() / 240};
    	update();
    }
    
    void OglViewerWidget::dragEnterEvent(QDragEnterEvent *e)
    {
    	if (e->mimeData()->hasUrls())
    		if(e->mimeData()->urls().size() == 1)
    			if(e->mimeData()->urls().first().toLocalFile().endsWith(".msh"))
    				e->acceptProposedAction();
    
    }
    
    void OglViewerWidget::dropEvent(QDropEvent * e)
    {
    	emit loadFile(e->mimeData()->urls().first().toLocalFile());
    }
    
    void OglViewerWidget::keyPressEvent(QKeyEvent *e)
    {
    	if (e->key() == Qt::Key_Space)
    	{
    		resetView();
    	}
    	else if (e->key() == Qt::Key_Escape)
    	{
    		parentWidget()->close();
    	}
    	else if (e->key() == Qt::Key_L)
    	{
    		updateLightPosition();
    		update();
    	}
    }
    
    void OglViewerWidget::initializeGL()
    {
    	initializeOpenGLFunctions();
    
    	glClearColor(0.5000f, 0.8000f, 1.0000f, 0.0000f);
    
    	initShaders();
    
    	// Enable depth buffer
    	glEnable(GL_DEPTH_TEST);
    
    	// Enable back face culling
    	//glEnable(GL_CULL_FACE);
    
    	// Enable transparency
    	glEnable(GL_BLEND);
    	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    	m_dataEngine = new GeometryEngine(this);
    	setConnections();
    }
    
    void OglViewerWidget::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 = 0.1, zFar = 100.0, fov = 45.0;
    
    	// Reset projection
    	m_projection.setToIdentity();
    
    	// Set perspective projection
    	m_projection.perspective(fov, aspect, zNear, zFar);
    }
    
    void OglViewerWidget::paintGL()
    {
    	// Clear color and depth buffer
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    	// Calculate model view transformation
    	QMatrix4x4 view;
    	view.translate(m_translation);
    	view.rotate(m_rotation);
    
    	// Set view-projection matrix
    	m_program.setUniformValue("vp_matrix", m_projection * view);
    
    	// Set Light values
    	m_program.setUniformValue("b_light", m_lightOn);
    	m_program.setUniformValue("light.position", m_light.position);
    	m_program.setUniformValue("light.intensities", m_light.intensities);
    
    	// Draw cube geometry
    	m_dataEngine->drawGeometry(&m_program, m_wireframe);
    }
    
    
    /////////////////////////////////////////////////////////////////////////
    // private functions
    
    void OglViewerWidget::initShaders()
    {
    	// Compile vertex shader
    	if (!m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl"))
    		close();
    
    	// Compile fragment shader
    	if (!m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl"))
    		close();
    
    	// Link shader pipeline
    	if (!m_program.link())
    		close();
    
    	// Bind shader pipeline for use
    	if (!m_program.bind())
    		close();
    }
    
    void OglViewerWidget::setConnections()
    {
    	connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView);
    	connect(parentWidget(), SIGNAL(loadFile(QString)), m_dataEngine, SLOT(loadFile(QString)));
    	connect(this, SIGNAL(loadFile(QString)), m_dataEngine, SLOT(loadFile(QString)));
    	connect(m_dataEngine, SIGNAL(sendMessage(QString, int)), parentWidget(), SLOT(printMessage(QString, int)));
    	connect(m_dataEngine, SIGNAL(requestUpdate()), this, SLOT(update()));
    	connect(m_dataEngine, SIGNAL(sendFileInfo(QString, QVector<Material>*, int, int)), parentWidget(), SLOT(setFileInfo(QString, QVector<Material>*, int, int)));
    
    }
    
    void OglViewerWidget::updateLightPosition()
    {
    	QMatrix4x4 rotateBack;
    	rotateBack.rotate(m_rotation.inverted());
    	m_light.position = rotateBack * (-m_translation);
    }
    
    
    /////////////////////////////////////////////////////////////////////////
    // private slots
    
    void OglViewerWidget::resetView()
    {
    	m_rotation = QQuaternion();
    	m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE };
    	update();
    }
    
    
    /////////////////////////////////////////////////////////////////////////
    // public slots
    
    void OglViewerWidget::changeDirection(int direction)
    {
    	switch (direction)
    	{
    	case 1:
    		m_rotDirections.x = !m_rotDirections.x;
    		break;
    	case 2:
    		m_rotDirections.y = !m_rotDirections.y;
    		break;
    	case 3:
    		m_rotDirections.z = !m_rotDirections.z;
    		break;
    	}
    }
    
    void OglViewerWidget::toggleWireframe()
    {
    	m_wireframe = 1 - m_wireframe;
    	update();
    }
    
    void OglViewerWidget::toggleLight()
    {
    	m_lightOn = 1 - m_lightOn;
    
    	if (m_lightOn)
    	{
    		glClearColor(m_light.intensities.x() / 100, m_light.intensities.y() / 100, m_light.intensities.z() / 100, 0.0000f);
    
    		updateLightPosition();
    	}
    	else
    	{
    		glClearColor(0.5000f, 0.8000f, 1.0000f, 0.0000f);
    	}
    
    	update();
    }