tuto_oper2.cpp 9.97 KB
Newer Older
1 2 3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
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.unistra.fr/                                           *
21 22 23 24 25 26
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include "tuto_oper2.h"
#include "Algo/Geometry/boundingbox.h"
untereiner's avatar
untereiner committed
27
#include "Algo/Tiling/Surface/square.h"
28
#include "Algo/Geometry/centroid.h"
Sylvain Thery's avatar
Sylvain Thery committed
29 30 31
#include "Algo/Import/import.h"
#include "Algo/Export/export.h"

32 33 34 35 36 37 38 39 40 41 42
using namespace CGoGN ;

int main(int argc, char **argv)
{
	//	// interface
	QApplication app(argc, argv);
	MyQT sqt;


    sqt.setDock(& sqt.dock);
    sqt.setCallBack( sqt.dock.listOper, SIGNAL(currentRowChanged(int)), SLOT(operation(int)) );
43 44
    sqt.setCallBack( sqt.dock.svg, SIGNAL(clicked()), SLOT(svg()) );
    sqt.setCallBack( sqt.dock.widthSlider, SIGNAL(valueChanged(int)), SLOT(width(int)) );
45 46 47 48 49 50 51
	int n=3;
	if (argc==2)
		n = atoi(argv[1]);

	// example code itself
	sqt.createMap(n);

Sylvain Thery's avatar
Sylvain Thery committed
52
	sqt.width(4.0);
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
	// set help message in menu
	sqt.setHelpMsg("First Tuto: \nCreate two faces\nsew them\nand affect positions");
	// final show for redraw
	sqt.show();
	// and wait for the end
	return app.exec();
}

void MyQT::operation(int x)
{
	switch(x)
	{
	case 0:
		CGoGNout <<"split vertex"<<CGoGNendl;
		if ((m_selected != NIL) && (m_selected2 != NIL))
		{
			dm.markAll();
			myMap.splitVertex(m_selected,m_selected2);
72 73
			PFP::VEC3 c1 = Algo::Surface::Geometry::faceCentroid<PFP>(myMap, m_selected, position);
			PFP::VEC3 c2 = Algo::Surface::Geometry::faceCentroid<PFP>(myMap, m_selected2, position);
74 75 76 77 78 79 80 81 82 83
			position[m_selected] = position[m_selected] * 0.7f + c1*0.3f;
			position[m_selected2] = position[m_selected2] * 0.7f + c2*0.3f;
			updateMap();
		}
		break;
	case 1:
		CGoGNout <<"delete vertex"<<CGoGNendl;
		if (m_selected != NIL)
		{
			dm.markAll();
Pierre Kraemer's avatar
Pierre Kraemer committed
84
			m_selected = myMap.deleteVertex(m_selected);
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
			updateMap();
		}
		break;
	case 2:
		CGoGNout <<"cut edge"<<CGoGNendl;
		if (m_selected != NIL)
		{
			dm.markAll();
			PFP::VEC3 Q = position[myMap.phi1(m_selected)];
			myMap.cutEdge(m_selected);
			position[myMap.phi1(m_selected)] = (position[m_selected] + Q)/2.0f;
			updateMap();
		}
		break;
	case 3:
		CGoGNout <<"uncut edge"<<CGoGNendl;
		if (m_selected != NIL)
		{
			myMap.uncutEdge(m_selected);
			updateMap();
		}
		break;
	case 4:
		CGoGNout <<"collapse edge"<<CGoGNendl;
		if (m_selected != NIL)
		{
			PFP::VEC3 M = (position[m_selected] + position[myMap.phi1(m_selected)])/2.0f;
112 113
			m_selected = myMap.collapseEdge(m_selected,true);
			position[m_selected] = M;
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
			updateMap();
		}
		break;
	case 5:
		CGoGNout <<"flip edge"<<CGoGNendl;
		if (m_selected != NIL)
		{
			myMap.flipEdge(m_selected);
			updateMap();
		}
		break;
	case 6:
		CGoGNout <<"flip back edge"<<CGoGNendl;
		if (m_selected != NIL)
		{
			myMap.flipBackEdge(m_selected);
			updateMap();
		}
		break;
	case 7:
		CGoGNout <<"split face"<<CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
135
		if ((m_selected != NIL) && (m_selected2 != NIL) && myMap.sameFace(m_selected,m_selected2))
136 137 138 139 140 141 142 143 144 145 146 147 148 149
		{
			myMap.splitFace(m_selected,m_selected2);
			updateMap();
		}
		break;
	case 8:
		CGoGNout <<"merge face"<<CGoGNendl;
		if (m_selected != NIL)
		{
			myMap.mergeFaces(m_selected);
			updateMap();
			m_selected=NIL;
		}
		break;
Sylvain Thery's avatar
Sylvain Thery committed
150 151 152 153 154 155 156 157 158 159
	case 9:
		CGoGNout <<"delete face"<<CGoGNendl;
		if (m_selected != NIL)
		{
			myMap.deleteFace(m_selected);
			updateMap();
			m_selected=NIL;
			m_selected2=NIL;
		}
		break;
Lionel Untereiner's avatar
Lionel Untereiner committed
160 161 162 163 164 165 166 167 168 169 170
	case 10:
		CGoGNout <<"split surface"<<CGoGNendl;
		if (!m_selecteds.empty())
		{
			myMap.splitSurface(m_selecteds);
			updateMap();
			m_selected=NIL;
			m_selected2=NIL;
			m_selecteds.clear();
		}
		break;
Sylvain Thery's avatar
Sylvain Thery committed
171

172 173 174 175 176 177 178 179 180 181
	default:
		break;
	}

	updateGL();
	dock.listOper->setCurrentRow(-1);
}

void MyQT::createMap(int n)
{
182
	position = myMap.addAttribute<VEC3, VERTEX, MAP>("position");
183

untereiner's avatar
untereiner committed
184 185
    Algo::Surface::Tilings::Square::Grid<PFP> grid(myMap, n, n, true);
    grid.embedIntoGrid(position, 1.,1.,0.);
186 187

    //  bounding box of scene
Sylvain Thery's avatar
Sylvain Thery committed
188 189 190
	Geom::BoundingBox<PFP::VEC3> bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position) ;
	setParamObject(bb.maxSize(), bb.center().data()) ;
	m_shift = bb.maxSize()/200.0f;
191 192 193 194 195 196 197 198

	// first show for be sure that GL context is binded
	show();

	// render the topo of the map without boundary darts

	dm.markAll();

199
	m_render_topo->setDartWidth(4.0f);
200
	m_render_topo->setInitialDartsColor(0.0f,0.0f,0.0f);
201
	m_render_topo->setInitialBoundaryDartsColor(0.0f,0.0f,0.0f);
untereiner's avatar
untereiner committed
202 203

#ifdef PRIMAL_TOPO
204
	m_render_topo->updateData<PFP>(myMap, position, 0.9);
untereiner's avatar
untereiner committed
205
#else
206
   m_render_topo->updateData<PFP>(myMap, position, 0.9f, 0.9f,true);
untereiner's avatar
untereiner committed
207
#endif
208 209 210 211 212

}

void MyQT::updateMap()
{
213
	m_render_topo->setInitialBoundaryDartsColor(0.0f,0.0f,0.0f);
untereiner's avatar
untereiner committed
214
#ifdef PRIMAL_TOPO
215
	m_render_topo->updateData<PFP>(myMap, position, 0.9);
untereiner's avatar
untereiner committed
216
#else
217
	m_render_topo->updateData<PFP>(myMap, position, 0.9f, 0.9f,true);
untereiner's avatar
untereiner committed
218 219
#endif

220 221 222 223 224 225
}

// initialization GL callback
void MyQT::cb_initGL()
{
	glClearColor(1.0f,1.0f,1.0f,1.0f);
untereiner's avatar
untereiner committed
226
#ifdef PRIMAL_TOPO
227
	m_render_topo = new Algo::Render::GL2::TopoPrimalRender() ;
untereiner's avatar
untereiner committed
228
#else
229
	m_render_topo = new Algo::Render::GL2::TopoRender(0.01f) ;
untereiner's avatar
untereiner committed
230
#endif
231 232 233 234 235
}

// redraw GL callback (clear and swap already done)
void MyQT::cb_redraw()
{
236
	glDepthFunc(GL_LESS);
237 238 239
	m_render_topo->drawTopo();

	if (m_selected != NIL)
240
		m_render_topo->overdrawDart(myMap, m_selected, 11, 1.0f, 0.0f, 0.0f);
241 242

	if (m_selected2 != NIL)
Sylvain Thery's avatar
Sylvain Thery committed
243
		m_render_topo->overdrawDart(myMap, m_selected2, 11, 0.0f, 1.0f, 0.0f);
Lionel Untereiner's avatar
Lionel Untereiner committed
244 245 246 247

	if(!m_selecteds.empty())
	{
		for(std::vector<Dart>::iterator it = m_selecteds.begin() ; it != m_selecteds.end() ; ++it)
248
			m_render_topo->overdrawDart(myMap, *it, 11, 0.0f, 0.0f, 1.0f);
Lionel Untereiner's avatar
Lionel Untereiner committed
249
	}
250

Sylvain Thery's avatar
Sylvain Thery committed
251
		
252

253 254 255 256 257 258
}

void MyQT::cb_mousePress(int button, int x, int y)
{
	if (Shift())
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
259
		Dart d = m_render_topo->picking(myMap, x,y); // nb
260 261 262 263 264 265 266 267 268 269 270 271
		if (button == Qt::LeftButton)
		{
			if (d != Dart::nil())
				m_selected = d;
		}
		if (button == Qt::RightButton)
		{
			if (d != Dart::nil())
				m_selected2 = d;
		}
		updateGL();
	}
Lionel Untereiner's avatar
Lionel Untereiner committed
272 273 274 275 276 277 278 279 280 281 282
	if(Control())
	{
		Dart d = m_render_topo->picking(myMap, x,y); // nb
		if (button == Qt::LeftButton)
		{
			if (d == Dart::nil())
				m_selecteds.clear();
			else
				m_selecteds.push_back(d);
		}
	}
283 284 285 286 287 288
}

void MyQT::cb_keyPress(int keycode)
{
	switch(keycode)
	{
Sylvain Thery's avatar
Sylvain Thery committed
289 290
	case Qt::Key_Up:
		if (m_selected!=NIL)
291
			position[m_selected][1] += m_shift;
Sylvain Thery's avatar
Sylvain Thery committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
		updateMap();
		updateGL();
		break;
	case Qt::Key_Down:
		if (m_selected!=NIL)
			position[m_selected][1] -= m_shift;
		updateMap();
		updateGL();
		break;
	case Qt::Key_Left:
		if (m_selected!=NIL)
			position[m_selected][0] -= m_shift;
		updateMap();
		updateGL();
		break;
	case Qt::Key_Right:
		if (m_selected!=NIL)
			position[m_selected][0] += m_shift;
		updateMap();
		updateGL();
		break;
Sylvain Thery's avatar
Sylvain Thery committed
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
	case '1':
		if (m_selected!=NIL)
			m_selected = myMap.phi1(m_selected);
		updateMap();
		updateGL();
		break;
	case '2':
		if (m_selected!=NIL)
			m_selected = myMap.phi2(m_selected);
		updateMap();
		updateGL();
		break;

	case ' ':
		m_selected=NIL;
		m_selected2=NIL;
		updateMap();
		updateGL();
		break;

333
	}
334 335
	updateGL();
}
336

337 338 339 340 341 342
void MyQT::svg()
{
	std::string filename = selectFileSave("snapshot file", ".", "(*.svg)");
	m_render_topo->svgout2D(filename, modelViewMatrix(),projectionMatrix());
}

Sylvain Thery's avatar
Sylvain Thery committed
343 344 345 346 347 348 349 350 351 352 353
void MyQT::cb_Open()
{
	std::string filters("all (*.*);; trian (*.trian);; off (*.off);; ply (*.ply);; map (*.map)") ;
	std::string filename = selectFile("Open Mesh", "", filters) ;
	if (!filename.empty())
		importMesh(filename);
	updateGL();
}

void MyQT::cb_Save()
{
354 355 356
	std::string filename = selectFileSave("Export Off file ",".","(*.off)");
	Algo::Surface::Export::exportOFF<PFP>(myMap,position,filename.c_str());
	//std::cout << "could not save file : " << filename << std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
357 358 359 360 361 362 363 364 365 366 367 368
}

void MyQT::importMesh(std::string& filename)
{
	myMap.clear(true) ;

	size_t pos = filename.rfind(".");    // position of "." in filename
	std::string extension = filename.substr(pos);

	if (extension == std::string(".map"))
	{
		myMap.loadMapBin(filename);
369
		position = myMap.getAttribute<VEC3, VERTEX, MAP>("position") ;
Sylvain Thery's avatar
Sylvain Thery committed
370 371 372 373
	}
	else
	{
		std::vector<std::string> attrNames ;
374
		if(!Algo::Surface::Import::importMesh<PFP>(myMap, filename.c_str(), attrNames))
Sylvain Thery's avatar
Sylvain Thery committed
375 376 377 378
		{
			CGoGNerr << "could not import " << filename << CGoGNendl ;
			return;
		}
379
		position = myMap.getAttribute<VEC3, VERTEX, MAP>(attrNames[0]) ;
Sylvain Thery's avatar
Sylvain Thery committed
380 381 382 383 384 385 386 387 388 389 390 391 392 393
	}


	m_selected  = NIL;
	m_selected2 = NIL;

	Geom::BoundingBox<PFP::VEC3> bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position) ;
	setParamObject(bb.maxSize(), bb.center().data()) ;
	m_shift = bb.maxSize()/200.0f;

	updateMap();
	updateGLMatrices() ;
}

394 395 396 397
void MyQT::width(int w)
{
	m_render_topo->setDartWidth(w);
	m_render_topo->setRelationWidth(w);
398 399
	updateGL();
}