1 /****************************************************************************
2 * MeshLab                                                           o o     *
3 * An extendible mesh processor                                    o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2005, 2009                                          \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 //#include <GL/glew.h>
25 
26 
27 #include <common/GLExtensionsManager.h>
28 #include "edit_align.h"
29 #include <QGLWidget>
30 #include "AlignPairWidget.h"
31 #include "AlignPairDialog.h"
32 #include <wrap/gl/pick.h>
33 
34 #include <wrap/qt/trackball.h>
35 #include <wrap/gl/picking.h>
36 #include <wrap/gl/space.h>
37 #include <wrap/qt/gl_label.h>
38 
39 #include <meshlab/glarea.h>
40 
41 
42 
AlignPairWidget(GLArea * ar,QWidget * parent)43 AlignPairWidget::AlignPairWidget(GLArea* ar, QWidget * parent)
44 	:QGLWidget(parent, ar->mvc()->sharedDataContext())
45 {
46 	gla = ar;
47 	shared = ar->mvc()->sharedDataContext();
48 	currentTrack = 0;
49 	freeMesh = 0;
50 	gluedTree = 0;
51 	tt[0] = &trackLeft;
52 	tt[1] = &trackRight;
53 	isUsingVertexColor = false;
54 	usePointRendering = false;
55 	freePickedPointVec.clear();
56 	gluedPickedPointVec.clear();
57 
58 	hasToPick = false;
59 	hasToDelete = false;
60 	pointToPick = vcg::Point2i(-1, -1);
61 	shared->addView(context());
62 	setAutoFillBackground(false);
63 }
64 
initMesh(MeshNode * _freeMesh,MeshTree * _gluedTree)65 void AlignPairWidget::initMesh(MeshNode *_freeMesh, MeshTree *_gluedTree)
66 {
67 	freeMesh = _freeMesh;
68 	gluedTree = _gluedTree;
69 	assert(freeMesh->glued == false);
70 	assert(gluedTree->gluedNum() > 0);
71 	update();
72 }
73 
initializeGL()74 void AlignPairWidget::initializeGL()
75 {
76 	if (shared == NULL)
77 		return;
78 
79 	GLExtensionsManager::initializeGLextensions();  //needed to init extensions, used by the aligner GL window while rendering
80 
81 	shared->addView(context());
82 	glClearColor(0, 0, 0, 0);
83 	glEnable(GL_LIGHTING);
84 	glEnable(GL_LIGHT0);
85 	glEnable(GL_NORMALIZE);
86 	glEnable(GL_COLOR_MATERIAL);
87 	glEnable(GL_CULL_FACE);
88 	glEnable(GL_DEPTH_TEST);
89 }
90 
paintEvent(QPaintEvent *)91 void AlignPairWidget::paintEvent(QPaintEvent *)
92 {
93 	if ((shared == NULL) || (gla == NULL))
94 		return;
95 	QPainter painter(this);
96 	painter.beginNativePainting();
97 	makeCurrent();
98 	if (!isValid())return;
99 
100 	glEnable(GL_DEPTH_TEST);
101 	glDepthMask(GL_TRUE);
102 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
103 
104 	if (freeMesh == 0 || gluedTree == 0) return;
105 
106 
107 	for (int i = 0; i < 2; ++i)
108 	{
109       if (i == 0)
110       {
111           MLRenderingData dt;
112           createRenderingData(freeMesh->m, dt);
113           shared->setRenderingDataPerMeshView(freeMesh->Id(), context(), dt);
114           shared->manageBuffers(freeMesh->Id());
115           glViewport(0, 0, (GLsizei)QTLogicalToDevice(this, width() / 2), (GLsizei)QTLogicalToDevice(this, height()));
116       }
117       else
118       {
119         for(auto ni=gluedTree->nodeMap.begin();ni!=gluedTree->nodeMap.end();++ni)
120         {
121           MeshNode *mn=ni->second;
122           if ((mn != NULL) && (mn->m != NULL) && mn->glued && mn != freeMesh && mn->m->visible)
123           {
124             MLRenderingData dt;
125             createRenderingData(mn->m, dt);
126             shared->setRenderingDataPerMeshView(mn->m->id(), context(), dt);
127             shared->manageBuffers(mn->m->id());
128           }
129         }
130         glViewport(QTLogicalToDevice(this, width() / 2), 0, (GLsizei)QTLogicalToDevice(this, width() / 2), (GLsizei)QTLogicalToDevice(this, height()));
131       }
132 
133 		glMatrixMode(GL_PROJECTION);
134 		glLoadIdentity();
135 		gluPerspective(30, (AlignPairWidget::width() / 2) / (float)AlignPairWidget::height(), 0.1, 100);
136 		glMatrixMode(GL_MODELVIEW);
137 		glLoadIdentity();
138 		gluLookAt(0, 0, 6, 0, 0, 0, 0, 1, 0);
139 		tt[i]->center = vcg::Point3f(0, 0, 0);
140 		tt[i]->radius = 1;
141 		tt[i]->GetView();
142 		tt[i]->Apply();
143 		vcg::Box3f bb;
144 		if (i == 0)
145 			bb.Add(freeMesh->tr(), freeMesh->bbox()); //bb.Import(freeMesh->bbox());
146 		else
147 			bb.Import(gluedTree->gluedBBox());
148 
149 		glPushMatrix();
150 		if (allowscaling)
151 			vcg::glScale(3.0f / bb.Diag());
152 		else
153 			vcg::glScale(3.0f / gluedTree->gluedBBox().Diag());
154 		vcg::glTranslate(-bb.Center());
155 		if (i == 0)
156 		{
157 			shared->draw(freeMesh->Id(), context());
158 			drawPickedPoints(&painter, freePickedPointVec, vcg::Color4b(vcg::Color4b::Red));
159 		}
160 		else
161 		{
162 //			foreach(MeshNode *mn, gluedTree->nodeList)
163           for(auto ni=gluedTree->nodeMap.begin();ni!=gluedTree->nodeMap.end();++ni)
164           {
165             MeshNode *mn=ni->second;
166 			if ((mn != NULL) && (mn->m != NULL) && mn->glued && mn != freeMesh && mn->m->visible)
167 			{
168               shared->draw(mn->m->id(), context());
169 			}
170           }
171           drawPickedPoints(&painter, gluedPickedPointVec, vcg::Color4b(vcg::Color4b::Blue));
172 		}
173 
174 		int pickSide = (pointToPick[0] < QTLogicalToDevice(this, (width() / 2))) ? 0 : 1;
175 		if (hasToPick && pickSide == i)
176 		{
177 			vcg::Point3f pp;
178 			hasToPick = false;
179 			if (vcg::Pick<vcg::Point3f>(pointToPick[0], pointToPick[1], pp))
180 			{
181 				std::vector<vcg::Point3f> &curVec = pickSide ? gluedPickedPointVec : freePickedPointVec;
182 
183 				qDebug("Picked point %i %i -> %f %f %f", pointToPick[0], pointToPick[1], pp[0], pp[1], pp[2]);
184 
185 				if (hasToDelete)
186 				{
187 					int bestInd = -1;
188 					double bestDist = 10e100;
189 					for (size_t i = 0; i < curVec.size(); ++i)
190 						if (Distance(pp, curVec[i]) < bestDist)
191 						{
192 							bestDist = Distance(pp, curVec[i]);
193 							bestInd = i;
194 						}
195 					hasToDelete = false;
196 					if (bestInd >= 0)
197 						curVec.erase(curVec.begin() + bestInd);
198 				}
199 				else curVec.push_back(pp);
200 				hasToPick = false;
201 				update();
202 			}
203 		}
204 		glPopMatrix();
205 		tt[i]->DrawPostApply();
206 	}
207 	painter.endNativePainting();
208 }
209 
drawPickedPoints(QPainter * qp,std::vector<vcg::Point3f> & pointVec,vcg::Color4b color)210 void AlignPairWidget::drawPickedPoints(QPainter *qp, std::vector<vcg::Point3f> &pointVec, vcg::Color4b color)
211 {
212 	glPushAttrib(GL_ENABLE_BIT | GL_POINT_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT);
213 	glDisable(GL_LIGHTING);
214 	glDisable(GL_TEXTURE);
215 	glDepthFunc(GL_ALWAYS);
216 	//glDisable(GL_DEPTH_TEST);
217 	for (uint i = 0; i < pointVec.size(); ++i)
218 	{
219 		vcg::Point3f &pt = pointVec[i];
220 		glPointSize(5.0);
221 		glColor(vcg::Color4b(vcg::Color4b::Black));
222 		glBegin(GL_POINTS);
223 		glVertex(pt);
224 		glEnd();
225 		glPointSize(3.0);
226 		glColor(color);
227 		glBegin(GL_POINTS);
228 		glVertex(pt);
229 		glEnd();
230 		vcg::glLabel::render(qp, pt, QString("%1").arg(i));
231 		//        renderText( pt[0],pt[1],pt[2], QString("%1").arg(i) );
232 	}
233 	glPopAttrib();
234 }
235 
cleanDataOnClosing(int)236 void AlignPairWidget::cleanDataOnClosing(int)
237 {
238 	if (shared == NULL)
239 		return;
240 
241 	shared->removeView(context());
242 }
243 
244 
createRenderingData(MeshModel * mm,MLRenderingData & dt)245 void AlignPairWidget::createRenderingData(MeshModel* mm, MLRenderingData& dt)
246 {
247 	if (mm == NULL)
248 		return;
249 
250 	MLRenderingData::RendAtts atts;
251 	MLPerViewGLOptions opts;
252 	atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
253 	atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true;
254 	atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = true;
255 	atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = (mm->hasDataMask(MeshModel::MM_VERTCOLOR)) && (isUsingVertexColor);
256 	dt.get(opts);
257 	if ((mm->cm.fn == 0) || (this->usePointRendering))
258 	{
259 		opts._perpoint_mesh_color_enabled = !isUsingVertexColor;
260 		opts._perpoint_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !opts._perpoint_mesh_color_enabled;
261 		dt.set(MLRenderingData::PR_POINTS, atts);
262 	}
263 	else
264 	{
265 		opts._persolid_mesh_color_enabled = !isUsingVertexColor;
266 		opts._persolid_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !opts._persolid_mesh_color_enabled;
267 		dt.set(MLRenderingData::PR_SOLID, atts);
268 	}
269 	dt.set(opts);
270 }
271 
keyReleaseEvent(QKeyEvent * e)272 void AlignPairWidget::keyReleaseEvent(QKeyEvent * e)
273 {
274 	e->ignore();
275 
276 	for (int i = 0; i < 2; ++i)
277 	{
278 		if (e->key() == Qt::Key_Control) tt[i]->ButtonUp(QT2VCG(Qt::NoButton, Qt::ControlModifier));
279 		if (e->key() == Qt::Key_Shift)   tt[i]->ButtonUp(QT2VCG(Qt::NoButton, Qt::ShiftModifier));
280 		if (e->key() == Qt::Key_Alt)     tt[i]->ButtonUp(QT2VCG(Qt::NoButton, Qt::AltModifier));
281 	}
282 	update();
283 }
284 
keyPressEvent(QKeyEvent * e)285 void AlignPairWidget::keyPressEvent(QKeyEvent * e)
286 {
287 	e->ignore();
288 	for (int i = 0; i < 2; ++i)
289 	{
290 		if (e->key() == Qt::Key_Control)  tt[i]->ButtonDown(QT2VCG(Qt::NoButton, Qt::ControlModifier));
291 		if (e->key() == Qt::Key_Shift)    tt[i]->ButtonDown(QT2VCG(Qt::NoButton, Qt::ShiftModifier));
292 		if (e->key() == Qt::Key_Alt)      tt[i]->ButtonDown(QT2VCG(Qt::NoButton, Qt::AltModifier));
293 	}
294 	update();
295 }
mouseDoubleClickEvent(QMouseEvent * e)296 void AlignPairWidget::mouseDoubleClickEvent(QMouseEvent * e)
297 {
298 	hasToPick = true;
299 	pointToPick = vcg::Point2i(QT2VCG_X(this, e), QT2VCG_Y(this, e));
300 	if (e->modifiers()&Qt::ControlModifier)
301 		hasToDelete = true;
302 	update();
303 
304 }
mousePressEvent(QMouseEvent * e)305 void AlignPairWidget::mousePressEvent(QMouseEvent * e)
306 {
307 	e->accept();
308 	setFocus();
309 	int index = e->x() < (width() / 2) ? 0 : 1;
310 	currentTrack = tt[index];
311 	currentTrack->MouseDown(QT2VCG_X(this, e), QT2VCG_Y(this, e), QT2VCG(e->button(), e->modifiers()));
312 }
313 
mouseMoveEvent(QMouseEvent * e)314 void AlignPairWidget::mouseMoveEvent(QMouseEvent * e)
315 {
316 	if (!currentTrack)
317 	{
318 		qDebug("Warning useless mousemove");
319 		return;
320 	}
321 
322 	if (e->buttons()&Qt::RightButton)
323 	{
324 		float lx, ly;
325 		lx = (e->x() / (float(width()) / 2.0f)) - 1.0;
326 		ly = ((height() - e->y()) / (float(height()) / 2.0f)) - 1.0;
327 		float lightPosF[] = { lx,ly,1.0,0.0 };
328 		glPushMatrix();
329 		glLoadIdentity();
330 		glLightfv(GL_LIGHT0, GL_POSITION, lightPosF);
331 		glPopMatrix();
332 		update();
333 	}
334 
335 	if (e->buttons()&Qt::LeftButton)
336 	{
337 		currentTrack->MouseMove(QT2VCG_X(this, e), QT2VCG_Y(this, e));
338 		update();
339 	}
340 }
341 
mouseReleaseEvent(QMouseEvent * e)342 void AlignPairWidget::mouseReleaseEvent(QMouseEvent * e)
343 {
344 	if (!currentTrack) {
345 		qDebug("Warning useless mouse release");
346 		return;
347 	}
348 	currentTrack->MouseUp(QT2VCG_X(this, e), QT2VCG_Y(this, e), QT2VCG(e->button(), e->modifiers()));
349 	currentTrack = 0;
350 }
351 
wheelEvent(QWheelEvent * e)352 void AlignPairWidget::wheelEvent(QWheelEvent * e)
353 {
354 	const int WHEEL_STEP = 120;
355 	//AlignPairDialog * dd = qobject_cast<AlignPairDialog *>(parent());
356 	if (allowscaling)
357 	{
358 		int index = e->x() < (width() / 2) ? 0 : 1;
359 		tt[index]->MouseWheel(e->delta() / float(WHEEL_STEP), QTWheel2VCG(e->modifiers()));
360 	}
361 	else
362 	{
363 		tt[0]->MouseWheel(e->delta() / float(WHEEL_STEP), QTWheel2VCG(e->modifiers()));
364 		tt[1]->MouseWheel(e->delta() / float(WHEEL_STEP), QTWheel2VCG(e->modifiers()));
365 	}
366 	update();
367 }
368