OglViewerWidget.cpp 8.78 KB
Newer Older
1
#include "..\Header\OglViewerWidget.h"
Anakin's avatar
Anakin committed
2
#include "..\Header\MainWindow.h"
Anakin's avatar
Anakin committed
3
4
5
#include "..\Header\FreeCamera.h"
#include "..\Header\OrbitCamera.h"
#include "..\Header\MoveCamera.h"
6
#include <QMouseEvent>
Anakin's avatar
Anakin committed
7
8
#include <QDropEvent>
#include <QMimeData>
Anakin's avatar
Anakin committed
9

10
11
#include "..\Header\Profiler.h"

Anakin's avatar
Anakin committed
12
#define DEFAULT_Z_DISTANCE -4.0
13

Anakin's avatar
Anakin committed
14
15

/////////////////////////////////////////////////////////////////////////
16
// constructor/destructor
Anakin's avatar
Anakin committed
17

Anakin's avatar
Anakin committed
18
19
OglViewerWidget::OglViewerWidget(QWidget *parent)
	: QOpenGLWidget(parent)
Anakin's avatar
Anakin committed
20
21
	, m_dataEngine(Q_NULLPTR)
	, m_camera(new FreeCamera)
22
{
23
	setFocus();
Anakin's avatar
Anakin committed
24
	setAcceptDrops(true);
Anakin's avatar
Anakin committed
25

Anakin's avatar
Anakin committed
26
	// settings window
Anakin's avatar
Anakin committed
27
28
	m_settings = new SettingsWindow(m_backgroundColorOff.toVector3D() * 255, m_backgroundColorOn.toVector3D() * 255, m_light.intensities * 255, true, m_light.ambientCoefficient, m_light.attenuationFactor, 1, this);

29
30
31
32
33
	connect(m_settings, &SettingsWindow::updateBGColorOff, this, &OglViewerWidget::setBGColorOff);
	connect(m_settings, &SettingsWindow::updateBGColorOn, this, &OglViewerWidget::setBGColorOn);
	connect(m_settings, &SettingsWindow::updateLightColor, this, &OglViewerWidget::setLightColor);
	connect(m_settings, &SettingsWindow::updateAttFac, this, &OglViewerWidget::setAttFac);
	connect(m_settings, &SettingsWindow::updateAmbCoef, this, &OglViewerWidget::setAmbCoef);
Anakin's avatar
Anakin committed
34
	connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight);
Anakin's avatar
Anakin committed
35
	connect(m_settings, &SettingsWindow::sendBackfaceCulling, this, &OglViewerWidget::setBackfaceCulling);
Anakin's avatar
Anakin committed
36
	connect(m_settings, &SettingsWindow::sendZommSpeed, [this](int value) {m_camera->setZoomSpeed(value); });
37
38
39
40
41
42
43
}

OglViewerWidget::~OglViewerWidget()
{
	// Make sure the context is current when deleting the texture
	// and the buffers.
	makeCurrent();
Anakin's avatar
Anakin committed
44
	delete m_dataEngine;
45
	doneCurrent();
Anakin's avatar
Anakin committed
46

Anakin's avatar
Anakin committed
47
	delete m_camera;
Anakin's avatar
Anakin committed
48
	delete m_settings;
49
50
}

Anakin's avatar
Anakin committed
51
52

/////////////////////////////////////////////////////////////////////////
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 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::resetView()
{
Anakin's avatar
Anakin committed
76
	m_camera->resetView();
Anakin's avatar
Anakin committed
77
78
79

	if (m_light.headlight)
		updateLightPosition();
80
81
82
83
84
	update();
}

void OglViewerWidget::updateLightPosition()
{
Anakin's avatar
Anakin committed
85
	QVector4D lightPosition = { 0,0,0,1 };
86

Anakin's avatar
Anakin committed
87
88
89
90
91
	lightPosition = m_camera->getMatrix().inverted() * lightPosition;

	m_light.position.setX(lightPosition.x());
	m_light.position.setY(lightPosition.y());
	m_light.position.setZ(lightPosition.z());
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
}

// OpenGL ///////////////////////////////////////////////////////////////

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

	// Enable depth buffer
	glEnable(GL_DEPTH_TEST);

	// Enable transparency
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	m_dataEngine = new GeometryEngine(this);
Anakin's avatar
Anakin committed
109
110
	connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView);
	connect(m_dataEngine, &GeometryEngine::requestUpdate, this, static_cast<void(OglViewerWidget::*)(void)>(&OglViewerWidget::update));
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
}

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()
{
	// set background color, last value is dirtybit
	if (m_lightOn && m_backgroundColorOn[3] == 1.0)
	{
		glClearColor(m_backgroundColorOn[0], m_backgroundColorOn[1], m_backgroundColorOn[2], 0.0000f);
		m_backgroundColorOn[3] = 0.0;
	}
	else if (!m_lightOn && m_backgroundColorOff[3] == 1.0)
	{
		glClearColor(m_backgroundColorOff[0], m_backgroundColorOff[1], m_backgroundColorOff[2], 0.0000f);
		m_backgroundColorOff[3] = 0.0;
	}

	// Clear color and depth buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Set view-projection matrix
Anakin's avatar
Anakin committed
146
	m_program.setUniformValue("vp_matrix", m_projection * m_camera->getMatrix());
147
148
149
150
151
152
153
154
155

	// 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);
	m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor);
	m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient);

	// Set camera position
Anakin's avatar
Anakin committed
156
	m_program.setUniformValue("cameraPosition", (m_camera->getMatrix().inverted() * QVector4D(0,0,0,1)).toVector3D());
157
158

	// Draw cube geometry
Anakin's avatar
Anakin committed
159
160
161
162
163
164
165
166
167
168
	if (m_backfaceCulling)
		glEnable(GL_CULL_FACE);

	if (m_wireframe)
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	m_dataEngine->drawGeometry(&m_program);

	glDisable(GL_CULL_FACE);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
169
170
171
}

// Inputs ///////////////////////////////////////////////////////////////
Anakin's avatar
Anakin committed
172

173
174
175
void OglViewerWidget::mousePressEvent(QMouseEvent *e)
{
	// Save mouse press position
176
177
178
179
180
181
182
	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;
183
184
185
186
}

void OglViewerWidget::mouseReleaseEvent(QMouseEvent *e)
{
187
188
189
190
191
	if (e->button() == Qt::LeftButton)
		m_mouse.left = false;
	else if (e->button() == Qt::RightButton)
		m_mouse.right = false;
}
192

193
194
195
196
197
void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
{
	if (m_mouse.left)
	{
		// get the difference between last press and now
Anakin's avatar
Anakin committed
198
		m_camera->rotateAction(QVector2D(e->localPos()) - m_mouse.position);
199

200
201
		// update the new position
		m_mouse.position = QVector2D(e->localPos());
202

Anakin's avatar
Anakin committed
203
		// request an update
Anakin's avatar
Anakin committed
204
205
		if (m_light.headlight)
			updateLightPosition();
Anakin's avatar
Anakin committed
206
207
208
209
210
		update();
	}
	else if (m_mouse.right)
	{
		// get the difference between last press and now
Anakin's avatar
Anakin committed
211
		m_camera->moveAction(QVector2D(e->localPos()) - m_mouse.position);
Anakin's avatar
Anakin committed
212
213
214
215

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

216
		// request an update
Anakin's avatar
Anakin committed
217
218
		if (m_light.headlight)
			updateLightPosition();
219
220
		update();
	}
221
222
}

Anakin's avatar
Anakin committed
223
224
void OglViewerWidget::wheelEvent(QWheelEvent *e)
{
Anakin's avatar
Anakin committed
225
	m_camera->wheelAction(e->angleDelta().y());
Anakin's avatar
Anakin committed
226
227
228
	
	if (m_light.headlight)
		updateLightPosition();
Anakin's avatar
Anakin committed
229
230
231
	update();
}

232
void OglViewerWidget::keyPressEvent(QKeyEvent *e)
233
{
234
	if (e->key() == Qt::Key_Space)
Anakin's avatar
Anakin committed
235
	{
Anakin's avatar
Anakin committed
236
		resetView();
Anakin's avatar
Anakin committed
237
	}
Anakin's avatar
Anakin committed
238
239
240
241
	else if (e->key() == Qt::Key_Escape)
	{
		parentWidget()->close();
	}
Anakin's avatar
Anakin committed
242
243
244
245
246
	else if (e->key() == Qt::Key_L)
	{
		updateLightPosition();
		update();
	}
247
248
}

249
void OglViewerWidget::dragEnterEvent(QDragEnterEvent *e)
Anakin's avatar
Anakin committed
250
{
251
252
253
254
	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
255

Anakin's avatar
Anakin committed
256
257
}

258
void OglViewerWidget::dropEvent(QDropEvent * e)
Anakin's avatar
Anakin committed
259
{
Anakin's avatar
Anakin committed
260
	m_dataEngine->loadFile(e->mimeData()->urls().first().toLocalFile());
Anakin's avatar
Anakin committed
261
}
Anakin's avatar
Anakin committed
262
263
264
265
266


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

Anakin's avatar
Anakin committed
267
268
269
270
271
void OglViewerWidget::loadFile(QString name)
{
	m_dataEngine->loadFile(name);
}

Anakin's avatar
Anakin committed
272
void OglViewerWidget::useFreeCamera()
Anakin's avatar
Anakin committed
273
{
Anakin's avatar
Anakin committed
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
	delete m_camera;
	m_camera = new FreeCamera;

	if (m_lightOn)
		updateLightPosition();
	update();
}

void OglViewerWidget::useOrbitCamera()
{
	delete m_camera;
	m_camera = new OrbitCamera;

	if (m_lightOn)
		updateLightPosition();
	update();
}

void OglViewerWidget::useMoveCamera()
{
	delete m_camera;
	m_camera = new MoveCamera;

	if (m_lightOn)
		updateLightPosition();
	update();
Anakin's avatar
Anakin committed
300
}
Anakin's avatar
Anakin committed
301
302
303

void OglViewerWidget::toggleWireframe()
{
304
	m_wireframe = !m_wireframe;
Anakin's avatar
Anakin committed
305
306
	update();
}
Anakin's avatar
Anakin committed
307
308
309

void OglViewerWidget::toggleLight()
{
310
	m_lightOn = !m_lightOn;
Anakin's avatar
Anakin committed
311
312
313

	if (m_lightOn)
	{
314
		m_backgroundColorOn[3] = 1.0;
Anakin's avatar
Anakin committed
315
316
317
318
		updateLightPosition();
	}
	else
	{
319
		m_backgroundColorOff[3] = 1.0;
Anakin's avatar
Anakin committed
320
	}
321

Anakin's avatar
Anakin committed
322
323
	update();
}
Anakin's avatar
Anakin committed
324
325
326
327
328

void OglViewerWidget::showSettings()
{
	m_settings->show();
}
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

void OglViewerWidget::setBGColorOff(QVector3D value)
{
	m_backgroundColorOff = QVector4D(value / 255, 1.0f);

	if (!m_lightOn)
		update();
}

void OglViewerWidget::setBGColorOn(QVector3D value)
{
	m_backgroundColorOn = QVector4D(value / 255, 1.0f);

	if (m_lightOn)
		update();
}

void OglViewerWidget::setLightColor(QVector3D value)
{
	m_light.intensities = value / 255;

	if (m_lightOn)
		update();
}

void OglViewerWidget::setAttFac(double value)
{
	m_light.attenuationFactor = (float)value;

	if (m_lightOn)
		update();
}

void OglViewerWidget::setAmbCoef(double value)
{
	m_light.ambientCoefficient = (float)value;

	if (m_lightOn)
		update();
}
Anakin's avatar
Anakin committed
369

Anakin's avatar
Anakin committed
370
371
372
void OglViewerWidget::setHeadlight(bool value)
{
	m_light.headlight = value;
373
374
375
376

	if (m_lightOn && value)
	{
		updateLightPosition();
Anakin's avatar
Anakin committed
377
		update();
378
	}
Anakin's avatar
Anakin committed
379
380
}

Anakin's avatar
Anakin committed
381
382
void OglViewerWidget::setBackfaceCulling(bool value)
{
Anakin's avatar
Anakin committed
383
	m_backfaceCulling = value;
Anakin's avatar
Anakin committed
384
385
	update();
}