OglViewerWidget.cpp 6.58 KB
Newer Older
1
#include "..\Header\OglViewerWidget.h"
Anakin's avatar
Anakin committed
2
#include "..\Header\MainWindow.h"
3
#include <QMouseEvent>
Anakin's avatar
Anakin committed
4 5
#include <QDropEvent>
#include <QMimeData>
6
#include <math.h>
Anakin's avatar
Anakin committed
7 8
#include <iostream>

Anakin's avatar
Anakin committed
9
#define DEFAULT_Z_DISTANCE -4.0
10

Anakin's avatar
Anakin committed
11 12 13 14

/////////////////////////////////////////////////////////////////////////
// public constructor/destructor

15 16
OglViewerWidget::OglViewerWidget(QWidget *parent) :
	QOpenGLWidget(parent),
Anakin's avatar
Anakin committed
17
	m_dataEngine(0)
18
{
19
	setFocus();
Anakin's avatar
Anakin committed
20
	m_translation.setZ(DEFAULT_Z_DISTANCE);
Anakin's avatar
Anakin committed
21
	setAcceptDrops(true);
Anakin's avatar
Anakin committed
22

23 24 25 26 27 28 29
}

OglViewerWidget::~OglViewerWidget()
{
	// Make sure the context is current when deleting the texture
	// and the buffers.
	makeCurrent();
Anakin's avatar
Anakin committed
30
	delete m_dataEngine;
31 32 33
	doneCurrent();
}

Anakin's avatar
Anakin committed
34 35 36 37

/////////////////////////////////////////////////////////////////////////
// protected functions

38 39 40
void OglViewerWidget::mousePressEvent(QMouseEvent *e)
{
	// Save mouse press position
41 42 43 44 45 46 47
	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;
48 49 50 51
}

void OglViewerWidget::mouseReleaseEvent(QMouseEvent *e)
{
52 53 54 55 56
	if (e->button() == Qt::LeftButton)
		m_mouse.left = false;
	else if (e->button() == Qt::RightButton)
		m_mouse.right = false;
}
57

58 59 60 61 62 63
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;
64

65 66
		// update the new position
		m_mouse.position = QVector2D(e->localPos());
67

68
		// calculate the rotation axis and rotate
Anakin's avatar
Anakin committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
		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;

			//std::cout << pitch << " - " << yaw << std::endl;

			//m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);

			m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0).normalized(), diff.x() * 0.5) + m_rotation;
			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, 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;
		}

		
Anakin's avatar
Anakin committed
102 103 104 105 106 107 108 109 110 111 112 113 114 115
		// 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};

116 117 118
		// request an update
		update();
	}
119 120
}

Anakin's avatar
Anakin committed
121 122 123 124 125 126
void OglViewerWidget::wheelEvent(QWheelEvent *e)
{
	m_translation += {0.0, 0.0, (float)e->angleDelta().y() / 240};
	update();
}

Anakin's avatar
Anakin committed
127 128 129 130 131 132 133 134 135
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();

}

Anakin's avatar
Anakin committed
136 137
void OglViewerWidget::dropEvent(QDropEvent * e)
{
Anakin's avatar
Anakin committed
138
	emit loadFile(e->mimeData()->urls().first().toLocalFile().toStdString().c_str());
Anakin's avatar
Anakin committed
139 140
}

141
void OglViewerWidget::keyPressEvent(QKeyEvent *e)
142
{
143
	if (e->key() == Qt::Key_Space)
Anakin's avatar
Anakin committed
144
	{
Anakin's avatar
Anakin committed
145
		resetView();
Anakin's avatar
Anakin committed
146
	}
Anakin's avatar
Anakin committed
147 148 149 150
	else if (e->key() == Qt::Key_Escape)
	{
		parentWidget()->close();
	}
151 152 153 154 155 156
}

void OglViewerWidget::initializeGL()
{
	initializeOpenGLFunctions();

Anakin's avatar
Anakin committed
157
	glClearColor(0.5000f, 0.8000f, 1.0000f, 0.0000f);
158 159 160 161 162 163 164 165 166

	initShaders();

	// Enable depth buffer
	glEnable(GL_DEPTH_TEST);

	// Enable back face culling
	glEnable(GL_CULL_FACE);

167 168
	m_dataEngine = new GeometryEngine(this);
	setConnections();
169 170 171 172 173 174 175 176
}

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
Anakin's avatar
Anakin committed
177
	const qreal zNear = 0.1, zFar = 100.0, fov = 45.0;
178 179

	// Reset projection
180
	m_projection.setToIdentity();
181 182

	// Set perspective projection
183
	m_projection.perspective(fov, aspect, zNear, zFar);
184 185 186 187 188 189 190 191
}

void OglViewerWidget::paintGL()
{
	// Clear color and depth buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Calculate model view transformation
Anakin's avatar
Anakin committed
192
	QMatrix4x4 view;
Anakin's avatar
Anakin committed
193
	view.translate(m_translation);
Anakin's avatar
Anakin committed
194
	view.rotate(m_rotation);
195

Anakin's avatar
Anakin committed
196 197
	// Set view-projection matrix
	m_program.setUniformValue("vp_matrix", m_projection * view);
198 199

	// Draw cube geometry
Anakin's avatar
Anakin committed
200
	m_dataEngine->drawGeometry(&m_program);
201
}
Anakin's avatar
Anakin committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225


/////////////////////////////////////////////////////////////////////////
// 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();
}

226 227 228 229 230
void OglViewerWidget::setConnections()
{
	connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView);
	connect(parentWidget(), SIGNAL(loadFile(const char*)), m_dataEngine, SLOT(loadFile(const char*)));
	connect(this, SIGNAL(loadFile(const char*)), m_dataEngine, SLOT(loadFile(const char*)));
Anakin's avatar
Anakin committed
231
	connect(m_dataEngine, SIGNAL(sendMessage(QString, int)), parentWidget(), SLOT(printMessage(QString, int)));
232 233 234
	connect(m_dataEngine, SIGNAL(requestUpdate()), this, SLOT(update()));
}

Anakin's avatar
Anakin committed
235 236

/////////////////////////////////////////////////////////////////////////
Anakin's avatar
Anakin committed
237
// private slots
Anakin's avatar
Anakin committed
238

Anakin's avatar
Anakin committed
239
void OglViewerWidget::resetView()
Anakin's avatar
Anakin committed
240
{
Anakin's avatar
Anakin committed
241 242 243 244
	m_rotation = QQuaternion();
	m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE };
	update();
}
Anakin's avatar
Anakin committed
245 246 247 248 249 250 251


/////////////////////////////////////////////////////////////////////////
// public slots

void OglViewerWidget::changeDirection(int direction)
{
Anakin's avatar
Anakin committed
252 253 254 255 256 257 258 259 260 261 262 263
	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;
	}
Anakin's avatar
Anakin committed
264
}