qtgl.cpp 9.56 KB
Newer Older
Sylvain Thery's avatar
Sylvain Thery committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
* Copyright (C) 2009, IGG Team, LSIIT, University of Strasbourg                *
*                                                                              *
* 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.           *
*                                                                              *
* Web site: https://iggservis.u-strasbg.fr/CGoGN/                              *
* 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"
Sylvain Thery's avatar
Sylvain Thery committed
32 33 34

namespace CGoGN
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
35

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

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

42

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

45

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

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

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

GLWidget::~GLWidget()
{
}

void GLWidget::setParamObject(float width, float* pos)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
71 72
	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
73 74 75 76
}

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

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

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

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

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

void GLWidget::recalcModelView()
{
100 101 102 103 104 105
	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
106
	glm::mat4 m;
107 108 109
	build_rotmatrixgl3(m, m_cbs->curquat());
	// update matrice
	m_cbs->modelViewMatrix() *= m;
Sylvain Thery's avatar
Sylvain Thery committed
110

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
	// ajout transformation in screen
	m_cbs->modelViewMatrix()*= m_cbs->transfoMatrix();

	// 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]);

	newModel = 0;

	if (m_cbs)
		m_cbs->cb_updateMatrix();

}

void GLWidget::changeCenterOfRotation(const glm::vec3& newCenter)
{
Sylvain Thery's avatar
Sylvain Thery committed
127
	oglPushModelViewMatrix();
128

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

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 143

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

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

148

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

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

	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];
160 161

	oglPopModelViewMatrix();
162 163

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

166

Sylvain Thery's avatar
Sylvain Thery committed
167 168 169 170 171 172 173 174 175 176
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
177 178
	if (w > 0) W = w;
	if (h > 0) H = h;
Sylvain Thery's avatar
Sylvain Thery committed
179

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
180
	glViewport(0, 0, W, H);
Sylvain Thery's avatar
Sylvain Thery committed
181
	float f = FAR_PLANE;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
182
	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
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

	recalcModelView();
}

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

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	if (m_cbs)
		m_cbs->cb_redraw();
}

void GLWidget::mousePressEvent(QMouseEvent* event)
{
	beginx = event->x();
	beginy = event->y();
201
	clickPoint = event->pos();
Sylvain Thery's avatar
Sylvain Thery committed
202 203 204
	m_current_button = event->button();

	if (m_cbs)
205
		m_cbs->cb_mousePress(event->button(), event->x(), getHeight() - event->y());
Sylvain Thery's avatar
Sylvain Thery committed
206 207 208 209 210
}

void GLWidget::mouseReleaseEvent(QMouseEvent* event)
{
	if (m_cbs)
211 212 213 214
		m_cbs->cb_mouseRelease(event->button(), event->x(), getHeight() - event->y());

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

217
void GLWidget::mouseClickEvent(QMouseEvent* event)
Sylvain Thery's avatar
Sylvain Thery committed
218
{
219

220 221 222
	if (m_cbs)
		m_cbs->cb_mouseClick(event->button(), event->x(), getHeight() - event->y());
}
Sylvain Thery's avatar
Sylvain Thery committed
223

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
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);
		}
	}
}


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

		switch (m_current_button)
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
253
		{
254 255 256 257 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
			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
283 284
		}

285 286 287 288 289
		beginx = x;
		beginy = y;
		newModel = 1;
		updateGL();
	}
Sylvain Thery's avatar
Sylvain Thery committed
290 291

	if (m_cbs)
292
		m_cbs->cb_mouseMove(event->button(), event->x(), getHeight() - event->y());
Sylvain Thery's avatar
Sylvain Thery committed
293 294
}

295
void GLWidget::wheelEvent(QWheelEvent* event)
Sylvain Thery's avatar
Sylvain Thery committed
296
{
297
	float wl = -0.05f * FAR_PLANE / foc;
Sylvain Thery's avatar
Sylvain Thery committed
298 299

	if (event->delta() > 0)
300
		m_cbs->trans_z() += wl;
Sylvain Thery's avatar
Sylvain Thery committed
301
	else
302
		m_cbs->trans_z() -= wl;
Sylvain Thery's avatar
Sylvain Thery committed
303 304 305

	newModel = 1;
	updateGL();
Pierre Kraemer's avatar
Pierre Kraemer committed
306 307 308

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

311
void GLWidget::keyPressEvent(QKeyEvent* event)
Sylvain Thery's avatar
Sylvain Thery committed
312 313 314 315
{
    if (event->key() == Qt::Key_Escape)
        close();
    else
Sylvain Thery's avatar
Sylvain Thery committed
316
    	QWidget::keyPressEvent(event);
Sylvain Thery's avatar
Sylvain Thery committed
317 318 319 320

    m_state_modifier = event->modifiers();

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

324
    if (m_cbs)
Sylvain Thery's avatar
Sylvain Thery committed
325 326 327 328 329
		m_cbs->cb_keyPress(k);
}

void GLWidget::keyReleaseEvent(QKeyEvent *event)
{
Sylvain Thery's avatar
Sylvain Thery committed
330 331
	QWidget::keyReleaseEvent(event);

Sylvain Thery's avatar
Sylvain Thery committed
332 333
	m_state_modifier = event->modifiers();
    int k = event->key();
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

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

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

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


Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
361
    if ( (k >= 65) && (k <= 91) && (event->modifiers() != Qt::ShiftModifier) )
362
    	k += 32;
Sylvain Thery's avatar
Sylvain Thery committed
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 389 390 391 392 393 394 395 396

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

void GLWidget::oglPushModelViewMatrix()
{
	m_stack_mv.push(m_cbs->modelViewMatrix());
}

bool GLWidget::oglPopModelViewMatrix()
{
	if (m_stack_mv.empty())
		return false;
	m_cbs->modelViewMatrix() = m_stack_mv.top();
	m_stack_mv.pop();
	return true;
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
397
} // namespace QT
Sylvain Thery's avatar
Sylvain Thery committed
398

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
399 400 401
} // namespace Utils

} // namespace CGoGN