qtgl.cpp 9.75 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
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
24

Sylvain Thery's avatar
Sylvain Thery committed
25 26 27 28 29 30
#include <GL/glew.h>
#include <iostream>
#include "Utils/qtgl.h"
#include "Utils/trackball.h"

#include "Utils/qtSimple.h"
31
#include "glm/gtc/type_precision.hpp"
32
#include "Utils/GLSLShader.h"
Sylvain Thery's avatar
Sylvain Thery committed
33 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

thery's avatar
thery committed
44
float GLWidget::FAR_PLANE=500.0f;
Sylvain Thery's avatar
Sylvain Thery committed
45

46

Sylvain Thery's avatar
Sylvain Thery committed
47
GLWidget::GLWidget(SimpleQT* cbs, QWidget *parent) :
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
48 49 50
	QGLWidget(QGLFormat(QGL::Rgba | QGL::DoubleBuffer| QGL::DepthBuffer), parent),
	m_cbs(cbs),
	m_state_modifier(0)
Sylvain Thery's avatar
Sylvain Thery committed
51 52 53 54 55
{
	makeCurrent();
	glewInit();

	newModel = 1;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
56 57
	m_cbs->trans_x() = 0.;
	m_cbs->trans_y() = 0.;
Sylvain Thery's avatar
Sylvain Thery committed
58
	float f = FAR_PLANE;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
59 60
	m_cbs->trans_z() = -f / 5.0f;
	foc = 2.0f;
Sylvain Thery's avatar
Sylvain Thery committed
61 62

	// init trackball
63
	trackball(m_cbs->curquat(), 0.0f, 0.0f, 0.0f, 0.0f);
Sylvain Thery's avatar
Sylvain Thery committed
64 65 66 67 68 69 70 71
}

GLWidget::~GLWidget()
{
}

void GLWidget::setParamObject(float width, float* pos)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
72 73
	m_obj_sc = ((FAR_PLANE / 5.0f) / foc) / width;
	m_obj_pos = glm::vec3(-pos[0], -pos[1], -pos[2]);
Sylvain Thery's avatar
Sylvain Thery committed
74 75 76 77
}

void  GLWidget::setFocal(float df)
{
78 79
	if (df > 5.0f)
		df = 5.0f;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
80 81
	if (df < 0.2f)
		df = 0.2f;
Sylvain Thery's avatar
Sylvain Thery committed
82

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
83
	m_obj_sc *= foc / df;
Sylvain Thery's avatar
Sylvain Thery committed
84 85

	foc = df;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
86
	resizeGL(W, H);
Sylvain Thery's avatar
Sylvain Thery committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100
}

QSize GLWidget::minimumSizeHint() const
{
    return QSize(200, 200);
}

QSize GLWidget::sizeHint() const
{
    return QSize(500, 500);
}

void GLWidget::recalcModelView()
{
101 102 103 104 105 106
	m_cbs->modelViewMatrix()= glm::mat4(1.0f);

	// positionne l'objet / mvt souris
	oglTranslate(m_cbs->trans_x(), m_cbs->trans_y(), m_cbs->trans_z());

	// tourne l'objet / mvt souris
Sylvain Thery's avatar
Sylvain Thery committed
107
	glm::mat4 m;
108
	build_rotmatrixgl3(m, m_cbs->curquat());
109
//	// update matrice
110
	m_cbs->modelViewMatrix() *= m;
Sylvain Thery's avatar
Sylvain Thery committed
111

112 113 114 115
	// transfo pour que l'objet soit centre et a la bonne taille
	oglScale(m_obj_sc, m_obj_sc, m_obj_sc);
	oglTranslate(m_obj_pos[0], m_obj_pos[1], m_obj_pos[2]);

116 117 118
	// ajout transformation
//	m_cbs->modelViewMatrix() *=m_cbs->transfoMatrix();

119 120 121 122 123 124 125 126
	newModel = 0;

	if (m_cbs)
		m_cbs->cb_updateMatrix();
}

void GLWidget::changeCenterOfRotation(const glm::vec3& newCenter)
{
127
	glm::mat4 storeMVM(m_cbs->modelViewMatrix());
128

129
	m_cbs->modelViewMatrix() = glm::mat4(1.0f);
130

Sylvain Thery's avatar
Sylvain Thery committed
131
	// positionne l'objet / mvt souris
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
132
	oglTranslate(m_cbs->trans_x(), m_cbs->trans_y(), m_cbs->trans_z());
Sylvain Thery's avatar
Sylvain Thery committed
133 134

	// tourne l'objet / mvt souris
135
	glm::mat4 m;
136
	build_rotmatrixgl3(m, m_cbs->curquat());
Sylvain Thery's avatar
Sylvain Thery committed
137 138 139
	// update matrice
	m_cbs->modelViewMatrix() *= m;

140 141 142
	// ajout transformation in screen
	m_cbs->modelViewMatrix()*= m_cbs->transfoMatrix();

Sylvain Thery's avatar
Sylvain Thery committed
143
	// transfo pour que l'objet soit centre et a la bonne taille
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
144
	oglScale(m_obj_sc, m_obj_sc, m_obj_sc);
Sylvain Thery's avatar
Sylvain Thery committed
145 146
	oglTranslate(m_obj_pos[0], m_obj_pos[1], m_obj_pos[2]);

147
	oglTranslate(newCenter[0], newCenter[1], newCenter[2]);
148
	oglScale(1.0f / m_obj_sc, 1.0f / m_obj_sc, 1.0f / m_obj_sc);
Sylvain Thery's avatar
Sylvain Thery committed
149

150
	m = glm::inverse(m_cbs->transfoMatrix());
151
	m_cbs->modelViewMatrix() *= m;
152 153 154 155 156 157

	matrix_to_quat( m_cbs->curquat(), m_cbs->modelViewMatrix());

	m_cbs->trans_x() = m_cbs->modelViewMatrix()[3][0];
	m_cbs->trans_y() = m_cbs->modelViewMatrix()[3][1];
	m_cbs->trans_z() = m_cbs->modelViewMatrix()[3][2];
158

159
	m_cbs->modelViewMatrix() = storeMVM;
160

161
	m_obj_pos = glm::vec3(-newCenter[0], -newCenter[1], -newCenter[2]);
Sylvain Thery's avatar
Sylvain Thery committed
162 163
}

164 165 166 167
glm::vec3& GLWidget::getObjPos()
{
	return m_obj_pos ;
}
168

Sylvain Thery's avatar
Sylvain Thery committed
169 170 171 172 173 174 175 176 177 178
void GLWidget::initializeGL()
{
	glEnable(GL_DEPTH_TEST);

	if (m_cbs)
		m_cbs->cb_initGL();
}

void GLWidget::resizeGL(int w, int h)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
179 180
	if (w > 0) W = w;
	if (h > 0) H = h;
Sylvain Thery's avatar
Sylvain Thery committed
181

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
182
	glViewport(0, 0, W, H);
Sylvain Thery's avatar
Sylvain Thery committed
183
	float f = FAR_PLANE;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
184
	m_cbs->projectionMatrix() = glm::frustum(-1.0f, 1.0f, -1.0f * H / W, 1.0f * H / W, foc, f);
Sylvain Thery's avatar
Sylvain Thery committed
185 186 187 188 189 190 191 192 193 194 195

	recalcModelView();
}

void GLWidget::paintGL()
{
	if (newModel)
	    recalcModelView();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	if (m_cbs)
196 197
	{
		Utils::GLSLShader::s_current_matrices = m_cbs->matricesPtr();
Sylvain Thery's avatar
Sylvain Thery committed
198
		m_cbs->cb_redraw();
199 200
	}

Sylvain Thery's avatar
Sylvain Thery committed
201 202 203 204 205 206
}

void GLWidget::mousePressEvent(QMouseEvent* event)
{
	beginx = event->x();
	beginy = event->y();
207
	clickPoint = event->pos();
Sylvain Thery's avatar
Sylvain Thery committed
208 209 210
	m_current_button = event->button();

	if (m_cbs)
211
		m_cbs->cb_mousePress(event->button(), event->x(), getHeight() - event->y());
Sylvain Thery's avatar
Sylvain Thery committed
212 213 214 215 216
}

void GLWidget::mouseReleaseEvent(QMouseEvent* event)
{
	if (m_cbs)
217 218 219 220
		m_cbs->cb_mouseRelease(event->button(), event->x(), getHeight() - event->y());

	if(event->pos() == clickPoint)
		mouseClickEvent(event) ;
Sylvain Thery's avatar
Sylvain Thery committed
221 222
}

223
void GLWidget::mouseClickEvent(QMouseEvent* event)
Sylvain Thery's avatar
Sylvain Thery committed
224
{
225

226 227 228
	if (m_cbs)
		m_cbs->cb_mouseClick(event->button(), event->x(), getHeight() - event->y());
}
Sylvain Thery's avatar
Sylvain Thery committed
229

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
void GLWidget::mouseDoubleClickEvent(QMouseEvent* event)
{
	if (event->button()==1)
	{
		GLint x = event->x();
		GLint y = getHeight() - event->y();
		GLfloat depth;
		glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
		if (depth < 1.0f)
		{
			glm::i32vec4 viewport;
			glGetIntegerv(GL_VIEWPORT, &(viewport[0]));
			glm::vec3 win(x, y, depth);
			glm::vec3 P = glm::unProject(win, m_cbs->modelViewMatrix(), m_cbs->projectionMatrix(), viewport);
			changeCenterOfRotation(P);
		}
	}
}

249 250
void GLWidget::mouseMoveEvent(QMouseEvent* event)
{
251
	// move object only if no special keys pressed
252
	if (!(m_state_modifier & ( Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)))
Sylvain Thery's avatar
Sylvain Thery committed
253
	{
254 255 256 257
		int x = event->x();
		int y = event->y();

		switch (m_current_button)
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
258
		{
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
			case Qt::RightButton:
			{
				float wl;
				if (m_cbs->trans_z() > -20.0f)
					wl = 20.0f / foc;
				else
					wl = -2.0f * m_cbs->trans_z() / foc;
				m_cbs->trans_x() += wl / W * (x - beginx);
				m_cbs->trans_y() += wl / H * (beginy - y);
			}
				break;
			case Qt::MidButton:
			{
				float wl = -0.5f * FAR_PLANE / foc;
				m_cbs->trans_z() -= wl / W * (x - beginx);
				m_cbs->trans_z() -= wl / H * (y - beginy);
			}
				break;
			case Qt::LeftButton:
			{
				trackball(
					m_cbs->lastquat(),
					(2.0f * beginx - W) / W,
					(H - 2.0f * beginy) / H,
					(2.0f * x - W) / W,(H - 2.0f * y) / H
				);
				add_quats(m_cbs->lastquat(), m_cbs->curquat(), m_cbs->curquat());
			}
				break;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
288 289
		}

290 291 292 293 294
		beginx = x;
		beginy = y;
		newModel = 1;
		updateGL();
	}
Sylvain Thery's avatar
Sylvain Thery committed
295 296

	if (m_cbs)
Sylvain Thery's avatar
Sylvain Thery committed
297
		m_cbs->cb_mouseMove(event->buttons(), event->x(), getHeight() - event->y());
Sylvain Thery's avatar
Sylvain Thery committed
298 299
}

300
void GLWidget::wheelEvent(QWheelEvent* event)
Sylvain Thery's avatar
Sylvain Thery committed
301
{
302 303 304
	if (!(m_state_modifier & ( Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)))
	{
		float wl = -0.05f * FAR_PLANE / foc;
Sylvain Thery's avatar
Sylvain Thery committed
305

306 307 308 309
		if (event->delta() > 0)
			m_cbs->trans_z() += wl;
		else
			m_cbs->trans_z() -= wl;
Sylvain Thery's avatar
Sylvain Thery committed
310

311 312 313
		newModel = 1;
		updateGL();
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
314 315 316

	if (m_cbs)
		m_cbs->cb_wheelEvent(event->delta(), event->x(), getHeight() - event->y());
Sylvain Thery's avatar
Sylvain Thery committed
317 318
}

319 320 321 322 323 324
void GLWidget::closeEvent(QCloseEvent *event)
{
	if (m_cbs)
		m_cbs->cb_exit() ;
}

325
void GLWidget::keyPressEvent(QKeyEvent* event)
Sylvain Thery's avatar
Sylvain Thery committed
326
{
327 328

	if (event->key() == Qt::Key_Escape)
Sylvain Thery's avatar
Sylvain Thery committed
329
        close();
330 331
//    else
//    	QWidget::keyPressEvent(event);
Sylvain Thery's avatar
Sylvain Thery committed
332 333 334 335

    m_state_modifier = event->modifiers();

    int k = event->key();
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
336 337
    if ( (k >= 65) && (k <= 91) && !(event->modifiers() & Qt::ShiftModifier) )
    	k += 32;
Sylvain Thery's avatar
Sylvain Thery committed
338

339
    if (m_cbs)
Sylvain Thery's avatar
Sylvain Thery committed
340 341 342 343 344
		m_cbs->cb_keyPress(k);
}

void GLWidget::keyReleaseEvent(QKeyEvent *event)
{
345
//	QWidget::keyReleaseEvent(event);
Sylvain Thery's avatar
Sylvain Thery committed
346

Sylvain Thery's avatar
Sylvain Thery committed
347 348
	m_state_modifier = event->modifiers();
    int k = event->key();
349 350

    // align on axis
351
	if ((k == 'Z') && (event->modifiers() & Qt::ShiftModifier))
352
	{
353 354 355
	    float Z[3] = { 0.0f, 0.0f, 1.0f };
		axis_to_quat(Z, 0.0f, m_cbs->curquat());
		newModel = 1;
356 357 358
		updateGL();
	}

359
	if ((k == 'Y') && (event->modifiers() & Qt::ShiftModifier))
360
	{
361 362 363
		float X[3] = { 1.0f, 0.0f, 0.0f };
		axis_to_quat(X, M_PI / 2.0f, m_cbs->curquat());
		newModel = 1;
364 365 366
		updateGL();
	}

367
	if ((k == 'X') && (event->modifiers() & Qt::ShiftModifier))
368
	{
369 370 371
		float Y[3] = { 0.0f, 1.0f, 0.0f };
		axis_to_quat(Y, -M_PI / 2.0f, m_cbs->curquat());
		newModel = 1;
372 373 374 375
		updateGL();
	}


Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
376
    if ( (k >= 65) && (k <= 91) && (event->modifiers() != Qt::ShiftModifier) )
377
    	k += 32;
Sylvain Thery's avatar
Sylvain Thery committed
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398

	if (m_cbs)
		m_cbs->cb_keyRelease(k);
}

void GLWidget::oglRotate(float angle, float x, float y, float z)
{
	m_cbs->modelViewMatrix() = glm::rotate(m_cbs->modelViewMatrix(), angle, glm::vec3(x,y,z));
}

void GLWidget::oglTranslate(float tx, float ty, float tz)
{
	m_cbs->modelViewMatrix() = glm::translate(m_cbs->modelViewMatrix(), glm::vec3(tx,ty,tz));
}

void GLWidget::oglScale(float sx, float sy, float sz)
{
	m_cbs->modelViewMatrix() = glm::scale(m_cbs->modelViewMatrix(), glm::vec3(sx,sy,sz));
}


Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
399
} // namespace QT
Sylvain Thery's avatar
Sylvain Thery committed
400

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
401 402 403
} // namespace Utils

} // namespace CGoGN