viewer.cpp 21.3 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*******************************************************************************
* 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.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
Pierre Kraemer's avatar
Pierre Kraemer committed
21 22 23 24 25 26 27 28 29 30 31 32
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include "viewer.h"

Viewer::Viewer() :
	m_renderStyle(FLAT),
	m_drawVertices(false),
	m_drawEdges(false),
	m_drawFaces(true),
	m_drawNormals(false),
33
	m_drawTopo(false),
34
	m_drawBoundaryTopo(false),
Pierre Kraemer's avatar
Pierre Kraemer committed
35 36 37 38 39
	m_render(NULL),
	m_phongShader(NULL),
	m_flatShader(NULL),
	m_vectorShader(NULL),
	m_simpleColorShader(NULL),
40 41
	m_pointSprite(NULL),
	m_nbFrames(0)
Pierre Kraemer's avatar
Pierre Kraemer committed
42 43
{
	normalScaleFactor = 1.0f ;
Sylvain Thery's avatar
MAJ MC  
Sylvain Thery committed
44
	vertexScaleFactor = 0.1f ;
Pierre Kraemer's avatar
Pierre Kraemer committed
45 46 47
	faceShrinkage = 1.0f ;

	colClear = Geom::Vec4f(0.2f, 0.2f, 0.2f, 0.1f) ;
48
	colDif = Geom::Vec4f(0.3f, 0.5f, 0.2f, 1.0f) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
49 50 51 52 53 54 55
	colSpec = Geom::Vec4f(0.9f, 0.9f, 0.9f, 1.0f) ;
	colNormal = Geom::Vec4f(1.0f, 0.0f, 0.0f, 1.0f) ;
	shininess = 80.0f ;
}

void Viewer::initGUI()
{
56
	setDock(&dock) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
57

58 59 60 61
	dock.check_drawVertices->setChecked(false) ;
	dock.check_drawEdges->setChecked(false) ;
	dock.check_drawFaces->setChecked(true) ;
	dock.check_drawNormals->setChecked(false) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
62

63 64
	dock.slider_verticesSize->setVisible(false) ;
	dock.slider_normalsSize->setVisible(false) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
65

66 67
	dock.slider_verticesSize->setSliderPosition(50) ;
	dock.slider_normalsSize->setSliderPosition(50) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
68 69 70 71 72 73

	setCallBack( dock.check_drawVertices, SIGNAL(toggled(bool)), SLOT(slot_drawVertices(bool)) ) ;
	setCallBack( dock.slider_verticesSize, SIGNAL(valueChanged(int)), SLOT(slot_verticesSize(int)) ) ;
	setCallBack( dock.check_drawEdges, SIGNAL(toggled(bool)), SLOT(slot_drawEdges(bool)) ) ;
	setCallBack( dock.check_drawFaces, SIGNAL(toggled(bool)), SLOT(slot_drawFaces(bool)) ) ;
	setCallBack( dock.combo_faceLighting, SIGNAL(currentIndexChanged(int)), SLOT(slot_faceLighting(int)) ) ;
74
	setCallBack( dock.check_drawTopo, SIGNAL(toggled(bool)), SLOT(slot_drawTopo(bool)) ) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
75 76 77 78 79 80
	setCallBack( dock.check_drawNormals, SIGNAL(toggled(bool)), SLOT(slot_drawNormals(bool)) ) ;
	setCallBack( dock.slider_normalsSize, SIGNAL(valueChanged(int)), SLOT(slot_normalsSize(int)) ) ;
}

void Viewer::cb_initGL()
{
81 82 83 84 85
	int major = 0;
	int minor = 0;
	glGetIntegerv(GL_MAJOR_VERSION, &major);
	glGetIntegerv(GL_MINOR_VERSION, &minor);
	CGoGNout <<"Using GL "<< major <<"."<< minor << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
86 87

	m_render = new Algo::Render::GL2::MapRender() ;
88
	m_topoRender = new Algo::Render::GL2::TopoRender() ;
89

90
	m_topoRender->setInitialDartsColor(1.0f, 1.00f, 1.00f) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
91 92 93 94

	m_positionVBO = new Utils::VBO() ;
	m_normalVBO = new Utils::VBO() ;

95
	m_phongShader = new Utils::ShaderPhong(true,false) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
96 97 98 99 100 101
	m_phongShader->setAttributePosition(m_positionVBO) ;
	m_phongShader->setAttributeNormal(m_normalVBO) ;
	m_phongShader->setAmbiant(colClear) ;
	m_phongShader->setDiffuse(colDif) ;
	m_phongShader->setSpecular(colSpec) ;
	m_phongShader->setShininess(shininess) ;
102
	m_phongShader->setBackColor(Geom::Vec4f(0.9f, 0.0f, 0.0f, 0.0f));
Pierre Kraemer's avatar
Pierre Kraemer committed
103

104
	m_flatShader = new Utils::ShaderSimpleFlat() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
105 106 107
	m_flatShader->setAttributePosition(m_positionVBO) ;
	m_flatShader->setAmbiant(colClear) ;
	m_flatShader->setDiffuse(colDif) ;
108
	m_flatShader->setBackColor(Geom::Vec4f(0.9f, 0.0f, 0.0f, 0.0f));
109

Pierre Kraemer's avatar
Pierre Kraemer committed
110 111 112 113 114 115

	m_vectorShader = new Utils::ShaderVectorPerVertex() ;
	m_vectorShader->setAttributePosition(m_positionVBO) ;
	m_vectorShader->setAttributeVector(m_normalVBO) ;
	m_vectorShader->setColor(colNormal) ;

116
	m_simpleColorShader = new Utils::ShaderSimpleColor(true) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
117
	m_simpleColorShader->setAttributePosition(m_positionVBO) ;
Sylvain Thery's avatar
Sylvain Thery committed
118
	Geom::Vec4f c(0.0f, 0.0f, 0.0f, 1.0f) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
119 120
	m_simpleColorShader->setColor(c) ;

121

Pierre Kraemer's avatar
Pierre Kraemer committed
122
	m_pointSprite = new Utils::PointSprite() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
123
	m_pointSprite->setAttributePosition(m_positionVBO) ;
124
	m_pointSprite->setColor(Geom::Vec4f(0.0f, 0.0f, 1.0f, 1.0f)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
125 126 127 128 129 130 131 132 133 134 135 136

	registerShader(m_phongShader) ;
	registerShader(m_flatShader) ;
	registerShader(m_vectorShader) ;
	registerShader(m_simpleColorShader) ;
	registerShader(m_pointSprite) ;
}

void Viewer::cb_redraw()
{
	if(m_drawVertices)
	{
137
		m_pointSprite->setSize(vertexScaleFactor) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
138 139 140 141 142
		m_render->draw(m_pointSprite, Algo::Render::GL2::POINTS) ;
	}

	if(m_drawEdges)
	{
143
		m_simpleColorShader->setColor(Geom::Vec4f(1.,1.,0.,0.));
Pierre Kraemer's avatar
Pierre Kraemer committed
144 145 146 147
		glLineWidth(1.0f) ;
		m_render->draw(m_simpleColorShader, Algo::Render::GL2::LINES) ;
	}

148 149 150 151 152 153
	if(m_drawTopo)
	{
		glDepthFunc(GL_LEQUAL);
		m_topoRender->drawTopo() ;
	}

Pierre Kraemer's avatar
Pierre Kraemer committed
154 155 156
	if(m_drawFaces)
	{
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) ;
157 158 159 160 161
		if (m_drawEdges||m_drawTopo)
		{
			glEnable(GL_POLYGON_OFFSET_FILL) ;
			glPolygonOffset(1.0f, 1.0f) ;
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
162 163 164 165 166 167 168 169 170 171 172
		switch(m_renderStyle)
		{
			case FLAT :
				m_render->draw(m_flatShader, Algo::Render::GL2::TRIANGLES) ;
				break ;
			case PHONG :
				m_render->draw(m_phongShader, Algo::Render::GL2::TRIANGLES) ;
				break ;
		}
		glDisable(GL_POLYGON_OFFSET_FILL) ;
	}
173

174

175 176 177 178 179 180 181 182

	if(m_drawNormals)
	{
		float size = normalBaseSize * normalScaleFactor ;
		m_vectorShader->setScale(size) ;
		glLineWidth(1.0f) ;
		m_render->draw(m_vectorShader, Algo::Render::GL2::POINTS) ;
	}
183 184

	m_nbFrames++;
185
	if (m_nbFrames >=500)
186 187 188 189 190
	{
		std::cout << 100000.0/m_frame_ch.elapsed()<< " fps"<<std::endl;
		m_nbFrames = 0;
		m_frame_ch.start();
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
191 192 193 194 195 196
}

void Viewer::cb_Open()
{
	std::string filters("all (*.*);; trian (*.trian);; ctm (*.ctm);; off (*.off);; ply (*.ply)") ;
	std::string filename = selectFile("Open Mesh", "", filters) ;
197 198
	if (filename.empty())
		return ;
Pierre Kraemer's avatar
Pierre Kraemer committed
199 200 201 202 203

	importMesh(filename) ;
	updateGL() ;
}

204 205
void Viewer::cb_Save()
{
206
	std::string filters("all (*.*);; map (*.map);; off (*.off);; ply (*.ply)") ;
207
	std::string filename = selectFileSave("Save Mesh", "", filters) ;
208

209 210
	if (!filename.empty())
		exportMesh(filename) ;
211 212
}

213 214
void Viewer::cb_keyPress(int keycode)
{
215
	switch(keycode)
Sylvain Thery's avatar
Sylvain Thery committed
216
	{
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
	case 'd':
	{
		m_phongShader->setDoubleSided(true);
		m_flatShader->setDoubleSided(true);
		updateGL();
	}
	break;
	case 'D':
	{
		m_phongShader->setDoubleSided(false);
		m_flatShader->setDoubleSided(false);
		updateGL();
	}
	break;

	case 'q':
	{
		Utils::Chrono ch;
		ch.start();

		for (int i = 0; i < 1000; ++i)
		{
			m_render->draw(m_flatShader, Algo::Render::GL2::TRIANGLES);
			glFlush();
		}

		std::cout << "speed render " << 1000.0*1000.0/ch.elapsed() << " fps " << std::endl;
	}
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
	case 'n':
		m_flatShader->setNoClippingPlane();
		m_phongShader->setNoClippingPlane();
		m_topoRender->setNoClippingPlane();
		m_simpleColorShader->setNoClippingPlane();
		m_pointSprite->setNoClippingPlane();
		m_vectorShader->setNoClippingPlane();

		break;
	case 'N':
	{
		const Geom::Vec3f& Pc = bb.center();
		const Geom::Vec3f& Nc = bb.diag();
		Geom::Vec4f planeClip(Nc[0],Nc[1],Nc[2],-(Pc*Nc));

		m_flatShader->setClippingPlane(planeClip);
		m_phongShader->setClippingPlane(planeClip);
		m_topoRender->setClippingPlane(planeClip);
		m_simpleColorShader->setClippingPlane(planeClip);
		m_pointSprite->setClippingPlane(planeClip);
		m_vectorShader->setClippingPlane(planeClip);

	}
		break;


271 272 273
		case 'c' :
			myMap.check();
			break;
Sylvain Thery's avatar
Sylvain Thery committed
274

275
		case 'a':
Sylvain Thery's avatar
Sylvain Thery committed
276
		{
277 278 279 280 281 282 283
			Utils::Chrono ch;
			ch.start();
			VertexAttribute<VEC3, MAP> pos2 = myMap.getAttribute<VEC3, VERTEX, MAP>("pos2") ;
			if(!pos2.isValid())
				pos2 = myMap.addAttribute<VEC3, VERTEX, MAP>("pos2") ;

			for (int i=0; i< 10; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
284
			{
285 286
				TraversorV<MAP> trav(myMap);
				for (Dart d=trav.begin(), d_end = trav.end(); d!=d_end ; d = trav.next())
Sylvain Thery's avatar
Sylvain Thery committed
287
				{
288 289 290 291 292 293 294 295 296
					pos2[d] = VEC3(0,0,0);
					int nb=0;
					Traversor2VVaF<MAP> trf(myMap,d);
					for (Dart e = trf.begin(),e_end =trf.end() ; e != e_end; e = trf.next())
					{
						pos2[d] += position[e];
						nb++;
					}
					pos2[d]/=nb;
Sylvain Thery's avatar
Sylvain Thery committed
297
				}
298
				myMap.swapAttributes(position, pos2);
Sylvain Thery's avatar
Sylvain Thery committed
299
			}
300 301 302 303 304
			std::cout << "Traversor "<< ch.elapsed()<< " ms "<< std::endl;
			Algo::Surface::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
			m_positionVBO->updateData(position) ;
			m_normalVBO->updateData(normal) ;
			updateGL();
Sylvain Thery's avatar
Sylvain Thery committed
305
		}
306
			break;
Sylvain Thery's avatar
Sylvain Thery committed
307

308 309 310 311
		case 'b':
		{
			Utils::Chrono ch;
			ch.start();
Sylvain Thery's avatar
Sylvain Thery committed
312

313 314 315
			VertexAttribute<VEC3,MAP> pos2 = myMap.getAttribute<VEC3, VERTEX, MAP>("pos2") ;
			if(!pos2.isValid())
				pos2 = myMap.addAttribute<VEC3, VERTEX, MAP>("pos2") ;
Sylvain Thery's avatar
Sylvain Thery committed
316

317
			for (int i=0; i< 6; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
318
			{
319
				foreach_cell<VERTEX>(myMap, [&] (Vertex d)
Sylvain Thery's avatar
Sylvain Thery committed
320
				{
321 322 323 324 325 326 327 328
					pos2[d] = VEC3(0,0,0);
					int nb=0;
					foreach_adjacent2<FACE>(myMap,d,[&](Vertex e)
					{
						pos2[d] += position[e];
						nb++;
					});
					pos2[d]/=nb;
Sylvain Thery's avatar
Sylvain Thery committed
329
				});
330 331 332 333 334 335 336
				myMap.swapAttributes(position,pos2);
			}
			std::cout << "Lambda "<< ch.elapsed()<< " ms "<< std::endl;
			Algo::Surface::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
			m_positionVBO->updateData(position) ;
			m_normalVBO->updateData(normal) ;
			updateGL();
Sylvain Thery's avatar
Sylvain Thery committed
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
			break;
		case 'B':
		{
			Utils::Chrono ch;
			ch.start();

			VertexAttribute<VEC3,MAP> pos2 = myMap.getAttribute<VEC3, VERTEX, MAP>("pos2") ;
			if(!pos2.isValid())
				pos2 = myMap.addAttribute<VEC3, VERTEX, MAP>("pos2") ;

			//		foreach_cell_EvenOddd<VERTEX>(myMap, [&] (Vertex d)
			//		{
			//			pos2[d] = VEC3(0,0,0);
			//			int nb=0;
			//			foreach_adjacent2<FACE>(myMap,d,[&](Vertex e)
			//			{
			//				pos2[d] += position[e];
			//				nb++;
			//			});
			//			pos2[d]/=nb;
			//		},
			//		[&] (Vertex d)
			//		{
			//			position[d] = VEC3(0,0,0);
			//			int nb=0;
			//			foreach_adjacent2<FACE>(myMap,d,[&](Vertex e)
			//			{
			//				position[d] += pos2[e];
			//				nb++;
			//			});
			//			position[d]/=nb;
			//		},
			//		3);

			//		std::cout << "Even/Odd "<< ch.elapsed()<< " ms "<< std::endl;
			Algo::Surface::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
			m_positionVBO->updateData(position) ;
			m_normalVBO->updateData(normal) ;
			updateGL();
		}
			break;
Sylvain Thery's avatar
Sylvain Thery committed
379

380
		case 'e':
Sylvain Thery's avatar
Sylvain Thery committed
381
		{
382 383 384 385 386 387 388
			Utils::Chrono ch;
			ch.start();
			VertexAttribute<VEC3,MAP> pos2 = myMap.getAttribute<VEC3, VERTEX, MAP>("pos2") ;
			if(!pos2.isValid())
				pos2 = myMap.addAttribute<VEC3, VERTEX, MAP>("pos2") ;

			for (int i=0; i< 10; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
389
			{
390 391
				TraversorV<MAP> trav(myMap);
				for (Dart d=trav.begin(), d_end = trav.end(); d!=d_end ; d = trav.next())
Sylvain Thery's avatar
Sylvain Thery committed
392
				{
393 394 395 396 397 398 399 400 401
					pos2[d] = VEC3(0,0,0);
					int nb=0;
					Traversor2VE<MAP> trf(myMap,d);
					for (Dart e = trf.begin(),e_end =trf.end() ; e != e_end; e = trf.next())
					{
						pos2[d] += position[myMap.phi1(e)];
						nb++;
					}
					pos2[d]/=nb;
Sylvain Thery's avatar
Sylvain Thery committed
402
				}
403
				myMap.swapAttributes(position,pos2);
Sylvain Thery's avatar
Sylvain Thery committed
404
			}
405 406 407 408 409
			std::cout << "Traversor "<< ch.elapsed()<< " ms "<< std::endl;
			Algo::Surface::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
			m_positionVBO->updateData(position) ;
			m_normalVBO->updateData(normal) ;
			updateGL();
Sylvain Thery's avatar
Sylvain Thery committed
410
		}
411
			break;
Sylvain Thery's avatar
Sylvain Thery committed
412

413 414 415 416
		case 'f':
		{
			Utils::Chrono ch;
			ch.start();
Sylvain Thery's avatar
Sylvain Thery committed
417

418 419 420
			VertexAttribute<VEC3,MAP> pos2 = myMap.getAttribute<VEC3, VERTEX, MAP>("pos2") ;
			if(!pos2.isValid())
				pos2 = myMap.addAttribute<VEC3, VERTEX, MAP>("pos2") ;
Sylvain Thery's avatar
Sylvain Thery committed
421

422
			for (int i=0; i< 10; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
423
			{
424
				foreach_cell<VERTEX>(myMap, [&] (Vertex d)
Sylvain Thery's avatar
Sylvain Thery committed
425
				{
426 427 428 429 430 431 432 433
					pos2[d] = VEC3(0,0,0);
					int nb=0;
					foreach_incident2<EDGE>(myMap,d,[&](Edge e)
					{
						pos2[d] += position[myMap.phi1(e)];
						nb++;
					});
					pos2[d]/=nb;
Sylvain Thery's avatar
Sylvain Thery committed
434
				});
435 436 437 438 439 440 441
				myMap.swapAttributes(position,pos2);
			}
			std::cout << "Lambda "<< ch.elapsed()<< " ms "<< std::endl;
			Algo::Surface::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
			m_positionVBO->updateData(position) ;
			m_normalVBO->updateData(normal) ;
			updateGL();
Sylvain Thery's avatar
Sylvain Thery committed
442
		}
443
			break;
Sylvain Thery's avatar
Sylvain Thery committed
444

445
		case'A':
446
		{
447 448 449 450
			myMap.disableQuickTraversal<VERTEX>() ;
#define NBLOOP 5
			Utils::Chrono ch;
			ch.start();
451
			{
452 453
				TraversorCell<MAP, VERTEX, FORCE_CELL_MARKING> trav(myMap,true);
				for(unsigned int i=0; i<NBLOOP; ++i)
454
				{
455 456 457 458
					for (Cell<VERTEX> v = trav.begin(), e = trav.end(); v.dart != e.dart; v = trav.next())
					{
						normal[v][0] = 0.0f;
					}
459
				}
460
				std::cout << "FORCE_CELL_MARKING "<< ch.elapsed()<< " ms "<< std::endl;
461
			}
Sylvain Thery's avatar
Sylvain Thery committed
462

463
			ch.start();
Sylvain Thery's avatar
Sylvain Thery committed
464
			{
465 466
				TraversorCell<MAP, VERTEX> trav(myMap);
				for(unsigned int i=0; i<NBLOOP; ++i)
467
				{
468 469 470 471
					for (Cell<VERTEX> v = trav.begin(), e = trav.end(); v.dart != e.dart; v = trav.next())
					{
						normal[v][0] = 0.0f;
					}
472
				}
473
				std::cout << "auto "<< ch.elapsed()<< " ms "<< std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
474
			}
475

476
			ch.start();
477
			{
478 479
				TraversorCell<MAP, VERTEX> trav(myMap,true);
				for(unsigned int i=0; i<NBLOOP; ++i)
480
				{
481 482 483 484
					for (Cell<VERTEX> v = trav.begin(), e = trav.end(); v.dart != e.dart; v = trav.next())
					{
						normal[v][0] = 0.0f;
					}
485
				}
486
				std::cout << "auto forcedart "<< ch.elapsed()<< " ms "<< std::endl;
487 488
			}

489
			ch.start();
490
			{
491 492
				TraversorCell<MAP, VERTEX, FORCE_DART_MARKING> trav(myMap,true);
				for(unsigned int i=0; i<NBLOOP; ++i)
493
				{
494 495 496 497
					for (Cell<VERTEX> v = trav.begin(), e = trav.end(); v.dart != e.dart; v = trav.next())
					{
						normal[v][0] = 0.0f;
					}
498
				}
499
				std::cout << "FORCE_DART_MARKING "<< ch.elapsed()<< " ms "<< std::endl;
500
			}
501 502
			myMap.enableQuickTraversal<MAP, VERTEX>() ;
			ch.start();
503
			{
504 505
				TraversorCell<MAP, VERTEX> trav(myMap);
				for(unsigned int i=0; i<NBLOOP; ++i)
506
				{
507 508 509 510
					for (Cell<VERTEX> v = trav.begin(), e = trav.end(); v.dart != e.dart; v = trav.next())
					{
						normal[v][0] = 0.0f;
					}
511
				}
512
				std::cout << "auto (quick) "<< ch.elapsed()<< " ms "<< std::endl;
513 514
			}

515
			ch.start();
516
			{
517 518
				TraversorCell<MAP, VERTEX, FORCE_QUICK_TRAVERSAL> trav(myMap);
				for(unsigned int i=0; i<NBLOOP; ++i)
519
				{
520 521 522 523
					for (Cell<VERTEX> v = trav.begin(), e = trav.end(); v.dart != e.dart; v = trav.next())
					{
						normal[v][0] = 0.0f;
					}
524
				}
525
				std::cout << "FORCE_QUICK_TRAVERSAL "<< ch.elapsed()<< " ms "<< std::endl;
526 527
			}

528 529
		}
			break;
Sylvain Thery's avatar
Sylvain Thery committed
530

531 532
		case'Z':
		{
Sylvain Thery's avatar
Sylvain Thery committed
533

534 535 536 537 538 539
			Utils::Chrono ch;
			ch.start();
			CGoGN::Parallel::NumberOfThreads = 1;
			for (unsigned int i=0; i<4; ++i)
				Algo::Surface::Geometry::Parallel::computeNormalVertices<PFP>(myMap, position, normal) ;
			std::cout << "Algo::Surface::Geometry::Parallel::computeNormalVertices1 "<< ch.elapsed()<< " ms "<< std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
540

541
			ch.start();
Sylvain Thery's avatar
Sylvain Thery committed
542
			CGoGN::Parallel::NumberOfThreads = 2;
543 544
			for (unsigned int i=0; i<4; ++i)
				Algo::Surface::Geometry::Parallel::computeNormalVertices<PFP>(myMap, position, normal) ;
Sylvain Thery's avatar
Sylvain Thery committed
545
			std::cout << "Algo::Surface::Geometry::Parallel::computeNormalVertices2 "<< ch.elapsed()<< " ms "<< std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
546

Sylvain Thery's avatar
Sylvain Thery committed
547
			ch.start();
Sylvain Thery's avatar
Sylvain Thery committed
548
			CGoGN::Parallel::NumberOfThreads = 3;
549 550
			for (unsigned int i=0; i<4; ++i)
				Algo::Surface::Geometry::Parallel::computeNormalVertices<PFP>(myMap, position, normal) ;
Sylvain Thery's avatar
Sylvain Thery committed
551
			std::cout << "Algo::Surface::Geometry::Parallel::computeNormalVertices3 "<< ch.elapsed()<< " ms "<< std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
552

553
			ch.start();
Sylvain Thery's avatar
Sylvain Thery committed
554 555 556 557
			CGoGN::Parallel::NumberOfThreads = 4;
			for (unsigned int i=0; i<4; ++i)
				Algo::Surface::Geometry::Parallel::computeNormalVertices<PFP>(myMap, position, normal) ;
			std::cout << "Algo::Surface::Geometry::Parallel::computeNormalVertices4 "<< ch.elapsed()<< " ms "<< std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
558

Sylvain Thery's avatar
Sylvain Thery committed
559 560
			ch.start();
			CGoGN::Parallel::NumberOfThreads = 8;
561
			for (unsigned int i=0; i<4; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
562 563
				Algo::Surface::Geometry::Parallel::computeNormalVertices<PFP>(myMap, position, normal) ;
			std::cout << "Algo::Surface::Geometry::Parallel::computeNormalVertices8 "<< ch.elapsed()<< " ms "<< std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
564 565


566 567 568 569 570 571 572 573 574
			//		ch.start();
			//		Parallel::foreach_cell_EO<VERTEX>(myMap,[&](Vertex v, unsigned int thr)
			//		{
			//			normal[v] = Algo::Surface::Geometry::vertexNormal<PFP>(myMap,v,position);
			//		},
			//		[&](Vertex v, unsigned int th)
			//		{
			//			normal[v] = Algo::Surface::Geometry::vertexNormal<PFP>(myMap,v,position);
			//		},2,4,false,FORCE_CELL_MARKING);
Sylvain Thery's avatar
Sylvain Thery committed
575

576
			//		std::cout << "Parallel::foreach_cell_EO "<< ch.elapsed()<< " ms "<< std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
577 578


579 580
		}
			break;
Sylvain Thery's avatar
Sylvain Thery committed
581 582


583 584 585
		default:
			break;
	}
586 587
}

Pierre Kraemer's avatar
Pierre Kraemer committed
588 589
void Viewer::importMesh(std::string& filename)
{
590 591
	myMap.clear(true) ;

592 593 594 595 596 597
	size_t pos = filename.rfind(".");    // position of "." in filename
	std::string extension = filename.substr(pos);

	if (extension == std::string(".map"))
	{
		myMap.loadMapBin(filename);
598
		position = myMap.getAttribute<VEC3, VERTEX, MAP>("position") ;
599 600
	}
	else
Pierre Kraemer's avatar
Pierre Kraemer committed
601
	{
602
		std::vector<std::string> attrNames ;
Sylvain Thery's avatar
Sylvain Thery committed
603
		if(!Algo::Surface::Import::importMesh<PFP>(myMap, filename, attrNames))
604 605 606 607
		{
			CGoGNerr << "could not import " << filename << CGoGNendl ;
			return;
		}
608
		position = myMap.getAttribute<PFP::VEC3, VERTEX, MAP>(attrNames[0]) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
609
	}
610

611
	//	myMap.enableQuickTraversal<VERTEX>() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
612

613 614 615

	std::cout << "The mesh is " << (myMap.isOpen() ? "open" : "closed") << std::endl;

616 617 618
	m_render->initPrimitives<PFP>(myMap, Algo::Render::GL2::POINTS) ;
	m_render->initPrimitives<PFP>(myMap, Algo::Render::GL2::LINES) ;
	m_render->initPrimitives<PFP>(myMap, Algo::Render::GL2::TRIANGLES) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
619

620
	m_topoRender->updateData<PFP>(myMap, position, 0.85f, 0.85f, m_drawBoundaryTopo, true) ;
621

622 623
	bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position) ;
	normalBaseSize = bb.diagSize() / 100.0f ;
624
	//	vertexBaseSize = normalBaseSize / 5.0f ;
Sylvain Thery's avatar
MAJ MC  
Sylvain Thery committed
625

626
	normal = myMap.getAttribute<VEC3, VERTEX, MAP>("normal") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
627
	if(!normal.isValid())
628
		normal = myMap.addAttribute<VEC3, VERTEX, MAP>("normal") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
629

Pierre Kraemer's avatar
Pierre Kraemer committed
630 631
	Utils::Chrono c;
	c.start();
632
	Algo::Surface::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
633
	std::cout << "compute normals -> " << c.elapsed() << std::endl;
Pierre Kraemer's avatar
Pierre Kraemer committed
634 635 636 637

	m_positionVBO->updateData(position) ;
	m_normalVBO->updateData(normal) ;

638
	setParamObject(bb.maxSize(), bb.center().data()) ;
639 640 641 642 643 644 645 646 647 648 649 650

	const Geom::Vec3f& Pc = bb.center();
	const Geom::Vec3f& Nc = bb.diag();
	Geom::Vec4f planeClip(Nc[0],Nc[1],Nc[2],-(Pc*Nc));

//	m_flatShader->setClippingPlane(planeClip);
//	m_phongShader->setClippingPlane(planeClip);
//	m_topoRender->setClippingPlane(planeClip);
//	m_simpleColorShader->setClippingPlane(planeClip);
//	m_pointSprite->setClippingPlane(planeClip);
//	m_vectorShader->setClippingPlane(planeClip);

Pierre Kraemer's avatar
Pierre Kraemer committed
651
	updateGLMatrices() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
652 653

	std::cout << "#vertices -> " << Algo::Topo::getNbOrbits<VERTEX>(myMap) << std::endl;
Pierre Kraemer's avatar
Pierre Kraemer committed
654 655
}

656
void Viewer::exportMesh(std::string& filename, bool askExportMode)
657
{
658 659
	size_t pos = filename.rfind(".") ;    // position of "." in filename
	std::string extension = filename.substr(pos) ;
660

661
	if (extension == std::string(".off"))
662
		Algo::Surface::Export::exportOFF<PFP>(myMap, position, filename.c_str()) ;
663
	else if (extension.compare(0, 4, std::string(".ply")) == 0)
664
	{
665
		int ascii = 0 ;
666 667 668
		if (askExportMode)
			Utils::QT::inputValues(Utils::QT::VarCombo("binary mode;ascii mode",ascii,"Save in")) ;

669
		std::vector<VertexAttribute<VEC3, MAP>*> attributes ;
670
		attributes.push_back(&position) ;
671
		Algo::Surface::Export::exportPLYnew<PFP>(myMap, attributes, filename.c_str(), !ascii) ;
672
	}
673 674
	else if (extension == std::string(".map"))
		myMap.saveMapBin(filename) ;
675 676
	else
		std::cerr << "Cannot save file " << filename << " : unknown or unhandled extension" << std::endl ;
677 678
}

Pierre Kraemer's avatar
Pierre Kraemer committed
679 680 681 682 683 684 685 686
void Viewer::slot_drawVertices(bool b)
{
	m_drawVertices = b ;
	updateGL() ;
}

void Viewer::slot_verticesSize(int i)
{
Sylvain Thery's avatar
MAJ MC  
Sylvain Thery committed
687
	vertexScaleFactor = i / 500.0f ;
Pierre Kraemer's avatar
Pierre Kraemer committed
688 689 690 691 692 693 694 695 696 697 698 699
	updateGL() ;
}

void Viewer::slot_drawEdges(bool b)
{
	m_drawEdges = b ;
	updateGL() ;
}

void Viewer::slot_drawFaces(bool b)
{
	m_drawFaces = b ;
Sylvain Thery's avatar
Sylvain Thery committed
700 701 702 703 704 705 706 707 708 709 710
	if (b)
	{
		Geom::Vec4f c(0.0f, 0.0f, 0.0f, 1.0f) ;
		m_simpleColorShader->setColor(c) ;
	}
	else
	{
		Geom::Vec4f c(0.9f, 0.9f, 0.1f, 1.0f) ;
		m_simpleColorShader->setColor(c) ;
	}

Pierre Kraemer's avatar
Pierre Kraemer committed
711 712 713 714 715 716 717 718 719
	updateGL() ;
}

void Viewer::slot_faceLighting(int i)
{
	m_renderStyle = i ;
	updateGL() ;
}

720 721 722 723 724 725
void Viewer::slot_drawTopo(bool b)
{
	m_drawTopo = b ;
	updateGL() ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
void Viewer::slot_drawNormals(bool b)
{
	m_drawNormals = b ;
	updateGL() ;
}

void Viewer::slot_normalsSize(int i)
{
	normalScaleFactor = i / 50.0f ;
	updateGL() ;
}

/**********************************************************************************************
 *                                      MAIN FUNCTION                                         *
 **********************************************************************************************/

int main(int argc, char **argv)
{
	QApplication app(argc, argv) ;

	Viewer sqt ;
	sqt.setGeometry(0, 0, 1000, 800) ;
748
	sqt.show() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
749

750
	if(argc >= 2)
Pierre Kraemer's avatar
Pierre Kraemer committed
751 752 753
	{
		std::string filename(argv[1]) ;
		sqt.importMesh(filename) ;
754 755 756 757
		if(argc >= 3)
		{
			std::string filenameExp(argv[2]) ;
			std::cout << "Exporting " << filename << " as " << filenameExp << " ... "<< std::flush ;
758
			sqt.exportMesh(filenameExp, false) ;
759 760 761 762
			std::cout << "done!" << std::endl ;

			return (0) ;
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
763 764 765 766 767 768
	}

	sqt.initGUI() ;

	return app.exec() ;
}