qtSimple.cpp 13 KB
Newer Older
Sylvain Thery's avatar
Sylvain Thery committed
1
2
3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg           *
Sylvain Thery's avatar
Sylvain Thery committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.u-strasbg.fr/                                         *
Sylvain Thery's avatar
Sylvain Thery committed
21
22
23
24
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

25
26
#include "Utils/Qt/qtSimple.h"
#include "Utils/Qt/qtgl.h"
27
28
29
#include "Utils/GLSLShader.h"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_precision.hpp"
30
#include "glm/gtc/type_ptr.hpp"
Sylvain Thery's avatar
Sylvain Thery committed
31

Sylvain Thery's avatar
Sylvain Thery committed
32
33
#include <QtGui/QTextEdit>

Sylvain Thery's avatar
Sylvain Thery committed
34
35
namespace CGoGN
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
36

Sylvain Thery's avatar
Sylvain Thery committed
37
38
namespace Utils
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
39

Sylvain Thery's avatar
Sylvain Thery committed
40
41
42
namespace QT
{

43
SimpleQT::SimpleQT() :
Pierre Kraemer's avatar
Pierre Kraemer committed
44
45
46
47
	m_dock(NULL),
	m_projection_matrix(m_mat.m_matrices[0]),
	m_modelView_matrix(m_mat.m_matrices[1]),
	m_transfo_matrix(m_mat.m_matrices[2])
Sylvain Thery's avatar
Sylvain Thery committed
48
49
50
51
52
{
	m_glWidget = new GLWidget(this);
	setCentralWidget(m_glWidget);
	setWindowTitle(tr("CGoGN"));

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
53
	m_fileMenu = menuBar()->addMenu(tr("&File"));
Sylvain Thery's avatar
Sylvain Thery committed
54

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
55
	QAction* action = new QAction(tr("New"), this);
Sylvain Thery's avatar
Sylvain Thery committed
56
57
58
	connect(action, SIGNAL(triggered()), this, SLOT(cb_New()));
	m_fileMenu->addAction(action);

Pierre Kraemer's avatar
Pierre Kraemer committed
59
	action = new QAction(tr("Open"), this);
Sylvain Thery's avatar
Sylvain Thery committed
60
61
62
	connect(action, SIGNAL(triggered()), this, SLOT(cb_Open()));
	m_fileMenu->addAction(action);

Pierre Kraemer's avatar
Pierre Kraemer committed
63
	action = new QAction(tr("Save"), this);
Sylvain Thery's avatar
Sylvain Thery committed
64
65
66
67
68
	connect(action, SIGNAL(triggered()), this, SLOT(cb_Save()));
	m_fileMenu->addAction(action);

	m_fileMenu->addSeparator();

Pierre Kraemer's avatar
Pierre Kraemer committed
69
	action = new QAction(tr("Quit"), this);
Sylvain Thery's avatar
Sylvain Thery committed
70
71
72
73
74
75
76
	connect(action, SIGNAL(triggered()), this, SLOT(cb_Quit()));
	m_fileMenu->addAction(action);

	m_appMenu = menuBar()->addMenu(tr("&Application"));

	QMenu* m_helpMenu = menuBar()->addMenu(tr("&Help"));

Pierre Kraemer's avatar
Pierre Kraemer committed
77
	action = new QAction(tr("console on/off"), this);
78
79
80
	connect(action, SIGNAL(triggered()), this, SLOT(cb_consoleOnOff()));
	m_helpMenu->addAction(action);

Pierre Kraemer's avatar
Pierre Kraemer committed
81
	action = new QAction(tr("console clear"), this);
82
83
84
	connect(action, SIGNAL(triggered()), this, SLOT(cb_consoleClear()));
	m_helpMenu->addAction(action);

Pierre Kraemer's avatar
Pierre Kraemer committed
85
	action = new QAction(tr("About"), this);
Sylvain Thery's avatar
Sylvain Thery committed
86
87
88
	connect(action, SIGNAL(triggered()), this, SLOT(cb_about()));
	m_helpMenu->addAction(action);

Pierre Kraemer's avatar
Pierre Kraemer committed
89
	action = new QAction(tr("About CGoGN"), this);
Sylvain Thery's avatar
Sylvain Thery committed
90
91
92
	connect(action, SIGNAL(triggered()), this, SLOT(cb_about_cgogn()));
	m_helpMenu->addAction(action);

Sylvain Thery's avatar
Sylvain Thery committed
93
94
	m_dockConsole = new QDockWidget(tr("Console"), this);
	m_dockConsole->setAllowedAreas(Qt::BottomDockWidgetArea);
Pierre Kraemer's avatar
Pierre Kraemer committed
95
	m_dockConsole->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable);
Sylvain Thery's avatar
Sylvain Thery committed
96
97
98
99
100
101
102
103
104
105
	addDockWidget(Qt::BottomDockWidgetArea, m_dockConsole);

	m_textConsole = new QTextEdit();
	m_textConsole->setLineWrapMode(QTextEdit::NoWrap);
	m_textConsole->setTabStopWidth(20);
	m_textConsole->setReadOnly(true);

	m_dockConsole->setWidget(m_textConsole);

	m_dockConsole->hide();
106
107

	m_transfo_matrix = glm::mat4(1.0f);
David Cazier's avatar
David Cazier committed
108
109

	resize(1200,800);
Sylvain Thery's avatar
Sylvain Thery committed
110
111
}

112
SimpleQT::SimpleQT(const SimpleQT& sqt):
Pierre Kraemer's avatar
Pierre Kraemer committed
113
114
115
116
117
	m_dock(NULL),
	m_mat(m_mat),
	m_projection_matrix(m_mat.m_matrices[0]),
	m_modelView_matrix(m_mat.m_matrices[1]),
	m_transfo_matrix(m_mat.m_matrices[2])
118
119
120
121
122
123
124
125
126
{
	m_glWidget = new GLWidget(this);
	setCentralWidget(m_glWidget);

	m_dock = new QDockWidget(sqt.m_dock) ;
	m_dockConsole = new QDockWidget(sqt.m_dockConsole) ;
	m_textConsole = new QTextEdit(sqt.m_textConsole) ;
	m_dockOn = sqt.m_dockOn ;

127

128
129
130
131
132
133
134
135
136
137
	for (unsigned int i = 0; i < 4; ++i)
	{
		m_curquat[i] = sqt.m_curquat[i];
		m_lastquat[i] = sqt.m_lastquat[i];
	}
	m_trans_x = sqt.m_trans_x ;
	m_trans_y = sqt.m_trans_y ;
	m_trans_z = sqt.m_trans_z ;
}

Sylvain Thery's avatar
Sylvain Thery committed
138
139
140
141
142
SimpleQT::~SimpleQT()
{
	delete m_glWidget; // ??
}

143
144
void SimpleQT::operator=(const SimpleQT& sqt)
{
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
	m_glWidget = new GLWidget(this);
	setCentralWidget(m_glWidget) ;

	m_dock = new QDockWidget(sqt.m_dock) ;
	m_dockConsole = new QDockWidget(sqt.m_dockConsole) ;
	m_textConsole = new QTextEdit(sqt.m_textConsole) ;
	m_dockOn = sqt.m_dockOn ;

	m_projection_matrix = sqt.m_projection_matrix;
	m_modelView_matrix = sqt.m_modelView_matrix;
	for (unsigned int i = 0; i < 4; ++i)
	{
		m_curquat[i] = sqt.m_curquat[i];
		m_lastquat[i] = sqt.m_lastquat[i];
	}
	m_trans_x = sqt.m_trans_x ;
	m_trans_y = sqt.m_trans_y ;
	m_trans_z = sqt.m_trans_z ;
}

165
void SimpleQT::setDock(QDockWidget *dock)
166
{
167
168
169
	m_dock = dock;
	addDockWidget(Qt::RightDockWidgetArea, m_dock);
	m_dock->show();
170
171
}

172
QDockWidget* SimpleQT::dockWidget()
173
{
174
	return m_dock;
175
176
}

177
void SimpleQT::setCallBack( const QObject* sender, const char* signal, const char* method)
Sylvain Thery's avatar
Sylvain Thery committed
178
{
179
	connect(sender, signal, this, method);
Sylvain Thery's avatar
Sylvain Thery committed
180
181
}

182
void SimpleQT::windowTitle(const char* windowTitle)
Sylvain Thery's avatar
Sylvain Thery committed
183
{
184
	setWindowTitle(tr(windowTitle));
Sylvain Thery's avatar
Sylvain Thery committed
185
186
}

187
void SimpleQT::dockTitle(const char* dockTitle)
Sylvain Thery's avatar
Sylvain Thery committed
188
{
189
190
	if (m_dock)
		m_dock->setWindowTitle(tr(dockTitle));
Sylvain Thery's avatar
Sylvain Thery committed
191
192
}

193
void SimpleQT::statusMsg(const char* msg, int timeoutms)
194
{
195
196
197
198
199
200
201
202
203
204
205
206
	if (msg)
	{
		QString message = tr(msg);
		statusBar()->showMessage(message,timeoutms);
	}
	else
	{
		if (statusBar()->isHidden())
			statusBar()->show();
		else
			statusBar()->hide();
	}
207
208
}

Sylvain Thery's avatar
Sylvain Thery committed
209
210
QDockWidget* SimpleQT::addEmptyDock()
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
211
212
213
214
	m_dock = new QDockWidget(tr("Control"), this);
	m_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
	m_dock->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetClosable);
	addDockWidget(Qt::RightDockWidgetArea, m_dock);
Sylvain Thery's avatar
Sylvain Thery committed
215

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
216
217
	m_dock->hide();
	return m_dock;
Sylvain Thery's avatar
Sylvain Thery committed
218
219
220
221
222
223
224
225
226
227
}

void SimpleQT::visibilityDock(bool visible)
{
	if (visible)
		m_dock->show();
	else
		m_dock->hide();
}

Sylvain Thery's avatar
Sylvain Thery committed
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
void SimpleQT::visibilityConsole(bool visible)
{
	if (visible)
		m_dockConsole->show();
	else
		m_dockConsole->hide();
}

void SimpleQT::toggleVisibilityDock()
{
	if (m_dock->isHidden())
		m_dock->show();
	else
		m_dock->hide();
}

void SimpleQT::toggleVisibilityConsole()
{
	if (m_dockConsole->isHidden())
		m_dockConsole->show();
	else
		m_dockConsole->hide();
}

252
void SimpleQT::add_menu_entry(const std::string label, const char* method)
Sylvain Thery's avatar
Sylvain Thery committed
253
{
254
255
256
	QAction * action = new QAction(tr(label.c_str()), this);
	connect(action, SIGNAL(triggered()), this, method);
	m_appMenu->addAction(action);
Sylvain Thery's avatar
Sylvain Thery committed
257
258
}

259
void SimpleQT::init_app_menu()
Sylvain Thery's avatar
Sylvain Thery committed
260
{
261
	m_appMenu->clear();
Sylvain Thery's avatar
Sylvain Thery committed
262
263
}

264
void SimpleQT::setHelpMsg(const std::string& msg)
265
{
266
	m_helpString = msg;
267
}
Sylvain Thery's avatar
Sylvain Thery committed
268

269
void SimpleQT::setGLWidgetMouseTracking(bool b)
Sylvain Thery's avatar
Sylvain Thery committed
270
{
271
	m_glWidget->setMouseTracking(b);
Sylvain Thery's avatar
Sylvain Thery committed
272
273
}

274
275
void SimpleQT::closeEvent(QCloseEvent *event)
{
276
277
278
279
	m_glWidget->closeEvent(event) ;
	QWidget::closeEvent(event) ;
}

Sylvain Thery's avatar
Sylvain Thery committed
280
281
void SimpleQT::keyPressEvent(QKeyEvent *e)
{
Sylvain Thery's avatar
Sylvain Thery committed
282
	if (e->modifiers() & Qt::ShiftModifier)
Sylvain Thery's avatar
Sylvain Thery committed
283
	{
Sylvain Thery's avatar
Sylvain Thery committed
284
285
		if ((e->key() == Qt::Key_Return))
			toggleVisibilityConsole();
Sylvain Thery's avatar
Sylvain Thery committed
286
	}
Sylvain Thery's avatar
Sylvain Thery committed
287
288
289
290
291
292
	else
	{
		if ((e->key() == Qt::Key_Return) && m_dock != NULL)
			toggleVisibilityDock();
	}

Sylvain Thery's avatar
Sylvain Thery committed
293
294
295
296
297
    if (e->key() == Qt::Key_Escape)
    	close();
    else
        QWidget::keyPressEvent(e);

Sylvain Thery's avatar
Sylvain Thery committed
298
    m_glWidget->keyPressEvent(e); // ?
Sylvain Thery's avatar
Sylvain Thery committed
299
300
301
302
}

void SimpleQT::keyReleaseEvent(QKeyEvent *e)
{
303
	QWidget::keyReleaseEvent(e);
Sylvain Thery's avatar
Sylvain Thery committed
304
305
306
    m_glWidget->keyReleaseEvent(e);
}

307
void SimpleQT::glMousePosition(int& x, int& y)
Sylvain Thery's avatar
Sylvain Thery committed
308
{
309
310
311
	QPoint xy = m_glWidget->mapFromGlobal(QCursor::pos());
	x = xy.x();
	y = m_glWidget->getHeight() - xy.y();
Sylvain Thery's avatar
Sylvain Thery committed
312
313
}

314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
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
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
//GLfloat SimpleQT::getOrthoScreenRay(int x, int y, Geom::Vec3f& rayA, Geom::Vec3f& rayB, int radius)
//{
//	// get Z from depth buffer
//	int yy = y;
//	GLfloat depth_t[25];
//	glReadPixels(x-2, yy-2, 5, 5, GL_DEPTH_COMPONENT, GL_FLOAT, depth_t);
//
//	GLfloat depth=0.0f;
//	unsigned int nb=0;
//	for (unsigned int i=0; i< 25; ++i)
//	{
//		if (depth_t[i] != 1.0f)
//		{
//			depth += depth_t[i];
//			nb++;
//		}
//	}
//	if (nb>0)
//		depth /= float(nb);
//	else
//		depth = 0.5f;
//
//	glm::i32vec4 viewport;
//	glGetIntegerv(GL_VIEWPORT, &(viewport[0]));
//
//	glm::vec3 win(x, yy, 0.0f);
//
//	glm::vec3 P = glm::unProject(win, m_modelView_matrix, m_projection_matrix, viewport);
//
//	rayA[0] = P[0];
//	rayA[1] = P[1];
//	rayA[2] = P[2];
//
//	win[2] = depth;
//
//	P = glm::unProject(win, m_modelView_matrix, m_projection_matrix, viewport);
//	rayB[0] = P[0];
//	rayB[1] = P[1];
//	rayB[2] = P[2];
//
//	if (depth == 1.0f)	// depth vary in [0-1]
//		win[2] = 0.5f;
//
//	win[0] += radius;
//	P = glm::unProject(win, m_modelView_matrix, m_projection_matrix, viewport);
//	Geom::Vec3f Q;
//	Q[0] = P[0];
//	Q[1] = P[1];
//	Q[2] = P[2];
//
//	// compute & return distance
//	Q -= rayB;
//	return float(Q.norm());
//}
//
//float SimpleQT::getWidthInWorld(unsigned int pixel_width, const Geom::Vec3f& center)
//{
//
//	glm::i32vec4 viewport;
//	glGetIntegerv(GL_VIEWPORT, &(viewport[0]));
//
//	glm::vec3 win = glm::project(glm::vec3(center[0],center[1],center[2]), m_modelView_matrix, m_projection_matrix, viewport);
//
//	win[0]-= pixel_width/2;
//
//	glm::vec3 P = glm::unProject(win, m_modelView_matrix, m_projection_matrix, viewport);
//
//	win[0] += pixel_width;
//
//	glm::vec3 Q = glm::unProject(win, m_modelView_matrix, m_projection_matrix, viewport);
//
//	return glm::distance(P,Q);
//}
//
389
390
391



392
393
void SimpleQT::synchronize(SimpleQT* sqt)
{
394
395
	m_glWidget->getObjPos() = sqt->m_glWidget->getObjPos() ;

396
397
	m_projection_matrix = sqt->m_projection_matrix;
	m_modelView_matrix = sqt->m_modelView_matrix;
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
398
	for (unsigned int i = 0; i < 4; ++i)
399
400
401
402
403
404
405
406
407
408
409
410
411
412
	{
		m_curquat[i] = sqt->m_curquat[i];
		m_lastquat[i] = sqt->m_lastquat[i];
	}
	m_trans_x = sqt->trans_x();
	m_trans_y = sqt->trans_y();
	m_trans_z = sqt->trans_z();

	SimpleQT::cb_updateMatrix();

	m_glWidget->modelModified();
	m_glWidget->updateGL();
}

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
413
void SimpleQT::registerShader(GLSLShader* ptr)
414
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
415
	GLSLShader::registerShader(this, ptr) ;
416
417
}

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
418
void SimpleQT::unregisterShader(GLSLShader* ptr)
419
{
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
420
	GLSLShader::unregisterShader(this, ptr) ;
421
422
}

423
void SimpleQT::cb_updateMatrix()
424
{
425
426
427
	glm::mat4 model(m_modelView_matrix);
	model *= m_transfo_matrix;

428
429
430
431
	if (GLSLShader::CURRENT_OGL_VERSION == 1)
	{
		glMatrixMode(GL_PROJECTION);
		glLoadMatrixf(glm::value_ptr(m_projection_matrix));
432

433
		glMatrixMode(GL_MODELVIEW);
434
		glLoadMatrixf(glm::value_ptr(model));
435
436
437
438
439
440
441
442
443
	}
	else
	{
		for(std::set< std::pair<void*, GLSLShader*> >::iterator it = GLSLShader::m_registeredShaders.begin();
			it != GLSLShader::m_registeredShaders.end();
			++it)
		{
			if ((it->first == NULL) || (it->first == this))
			{
444
				it->second->updateMatrices(m_projection_matrix, model);
445
446
447
448
			}
		}
	}
}
449

450
451
452
void SimpleQT::updateGL()
{
	m_glWidget->updateGL();
453
454
}

455
456
457
void SimpleQT::updateGLMatrices()
{
	m_glWidget->modelModified();
Pierre Kraemer's avatar
Pierre Kraemer committed
458
//	m_glWidget->updateGL();
459
}
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

void SimpleQT::transfoRotate(float angle, float x, float y, float z)
{
	transfoMatrix() = glm::rotate(transfoMatrix(), angle, glm::vec3(x,y,z));
}

void SimpleQT::transfoTranslate(float tx, float ty, float tz)
{
	transfoMatrix() = glm::translate(transfoMatrix(), glm::vec3(tx,ty,tz));
}

void SimpleQT::transfoScale(float sx, float sy, float sz)
{
	transfoMatrix() = glm::scale(transfoMatrix(), glm::vec3(sx,sy,sz));
}

void SimpleQT::pushTransfoMatrix()
{
	m_stack_trf.push(transfoMatrix());
}

bool SimpleQT::popTransfoMatrix()
{
	if (m_stack_trf.empty())
		return false;
	transfoMatrix() = m_stack_trf.top();
	m_stack_trf.pop();
	return true;
}

490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
std::string SimpleQT::selectFile(const std::string& title, const std::string& dir, const std::string& filters)
{
    QString fileName = QFileDialog::getOpenFileName(this, tr(title.c_str()), tr(dir.c_str()), tr(filters.c_str()), 0, 0);
    return fileName.toStdString();
}

std::string SimpleQT::selectFileSave(const std::string& title, const std::string& dir, const std::string& filters)
{
    QString fileName = QFileDialog::getSaveFileName(this, tr(title.c_str()), tr(dir.c_str()), tr(filters.c_str()), 0, 0);
    return fileName.toStdString();
}

void SimpleQT::cb_about_cgogn()
{
	QString str("CGoGN:\nCombinatorial and Geometric modeling\n"
				"with Generic N-dimensional Maps\n"
				"Web site: https://cgogn.u-strasbg.fr \n"
				"Contact information: cgogn@unistra.fr");
	QMessageBox::about(this, tr("About CGoGN"), str);
}

void SimpleQT::cb_about()
{
   QMessageBox::about(this, tr("About App"), m_helpString.c_str());
}
515

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
516
} // namespace QT
Sylvain Thery's avatar
Sylvain Thery committed
517

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
518
} // namespace Utils
Sylvain Thery's avatar
Sylvain Thery committed
519

Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
520
} // namespace CGoGN