tuto_mt.cpp 9.68 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-2012, 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.unistra.fr/                                           *
Sylvain Thery's avatar
Sylvain Thery committed
21
22
23
24
25
26
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include <iostream>

27
#include "tuto_mt.h"
Sylvain Thery's avatar
Sylvain Thery committed
28
29

#include "Topology/generic/parameters.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
30
#include "Topology/map/embeddedMap2.h"
Sylvain Thery's avatar
Sylvain Thery committed
31
32
33
34
35

#include "Geometry/vector_gen.h"

#include "Algo/Import/import.h"
#include "Algo/Geometry/boundingbox.h"
36
#include "Utils/GLSLShader.h"
37
//#include "Algo/Geometry/area.h"
Sylvain Thery's avatar
Sylvain Thery committed
38
#include "Algo/Geometry/normal.h"
39
40
#include "Algo/Modelisation/polyhedron.h"

Sylvain Thery's avatar
Sylvain Thery committed
41
#include "Algo/Parallel/parallel_foreach.h"
42
#include "Algo/Parallel/cgogn_thread.h"
43
#include "Utils/cgognStream.h"
44
#include "Utils/chrono.h"
Sylvain Thery's avatar
Sylvain Thery committed
45
46
47
48
49
50
51
52
53
54

using namespace CGoGN ;

/**
 * Struct that contains some informations about the types of the manipulated objects
 * Mainly here to be used by the algorithms that are parameterized by it
 */
struct PFP: public PFP_STANDARD
{
	// definition of the map
Pierre Kraemer's avatar
Pierre Kraemer committed
55
	typedef EmbeddedMap2 MAP;
Sylvain Thery's avatar
Sylvain Thery committed
56
57
};

58

59
PFP::MAP myMap;
60
VertexAttribute<PFP::VEC3> position;
61
VertexAttribute<PFP::VEC3> position2;
62
VertexAttribute<PFP::VEC3> normal;
63

Sylvain Thery's avatar
Sylvain Thery committed
64

65

Sylvain Thery's avatar
Sylvain Thery committed
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
template <typename XXX>
class ThreadNormals: public Algo::Parallel::CGoGNThread<typename XXX::MAP>
{
protected:
	VertexAttribute<typename XXX::VEC3>& m_positions;
	VertexAttribute<typename XXX::VEC3>& m_normals;
public:
	ThreadNormals(typename XXX::MAP& map, VertexAttribute<typename XXX::VEC3>& pos, VertexAttribute<typename XXX::VEC3>& norm, unsigned int th):
		Algo::Parallel::CGoGNThread<typename XXX::MAP>(map,th),
		m_positions(pos),
		m_normals(norm)
	{}

	void operator()()
	{
		Algo::Geometry::computeNormalVertices<XXX>(this->m_map, m_positions, m_normals, SelectorTrue(), this->tid());
	}
};
85
86
87



88
void MyQT::cb_initGL()
Sylvain Thery's avatar
Sylvain Thery committed
89
{
90
	Utils::GLSLShader::setCurrentOGLVersion(2);
Sylvain Thery's avatar
Sylvain Thery committed
91

92
93
	// create the render
	m_render = new Algo::Render::GL2::MapRender();
Sylvain Thery's avatar
Sylvain Thery committed
94

95
96
97
 	// create VBO for position
	m_positionVBO = new Utils::VBO();
	m_positionVBO->updateData(position);
98

99
	m_normalVBO =  new Utils::VBO();
100

101
102
103
	m_shader = new Utils::ShaderSimpleColor();
	m_shader->setAttributePosition(m_positionVBO);
	m_shader->setColor(Geom::Vec4f(1.,1.,0.,0.));
104
105


106
107
108
109
110
	m_lines = new Utils::ShaderVectorPerVertex();
	m_lines->setAttributePosition(m_positionVBO);
	m_lines->setAttributeVector(m_normalVBO);
	m_lines->setScale(2.0f);
	m_lines->setColor(Geom::Vec4f(0.0f, 1.0f, 0.2f, 0.0f));
111

112
	CGoGNout << "Je calcule les normales en meme temps que les primitives" << CGoGNendl;
113
	boost::thread thread1( ThreadNormals<PFP>(myMap,position,normal,1));
114
115


116
117
	m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::LINES);
	m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::POINTS);
118

119
120
121
122
123
124
	registerShader(m_shader);
	registerShader(m_lines);

	// on attend la fin du thread pour etre sur que normal est a jour
	thread1.join();
	m_normalVBO->updateData(normal);
Sylvain Thery's avatar
Sylvain Thery committed
125

126
}
Sylvain Thery's avatar
Sylvain Thery committed
127

128
129
void MyQT::cb_redraw()
{
130
131
	m_render->draw(m_shader, Algo::Render::GL2::LINES);
	m_render->draw(m_lines, Algo::Render::GL2::POINTS);
Sylvain Thery's avatar
Sylvain Thery committed
132
133
134
}


135
void MyQT::cb_keyPress(int code)
Sylvain Thery's avatar
Sylvain Thery committed
136
{
137
138
	Utils::Chrono ch;
	ch.start();
Sylvain Thery's avatar
Sylvain Thery committed
139

140
	switch(code)
Sylvain Thery's avatar
Sylvain Thery committed
141
	{
142
143
144
145
146
147
148
149
150
151
152
	case 'a':
		threadSimple();
		break;
	case 'z':
		threadStorage();
		break;
	case 'q':
		threadAttrib();
		break;
	default:
		break;
Sylvain Thery's avatar
Sylvain Thery committed
153
	}
154
	CGoGNout << "time = "<< ch.elapsed() << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
155

156
157
	updateGL();
}
Sylvain Thery's avatar
Sylvain Thery committed
158
159


160
161
162
163

//
// Simple attribute parallel functor and traversor
//
164
template <typename XXX>
165
class UnshrinkFunctor : public FunctorAttribThreaded
Sylvain Thery's avatar
Sylvain Thery committed
166
167
{
protected:
168
169
	VertexAttribute<typename XXX::VEC3>& m_positions;
	VertexAttribute<typename XXX::VEC3>& m_positions2;
Sylvain Thery's avatar
Sylvain Thery committed
170
public:
171
172
	UnshrinkFunctor( VertexAttribute<typename XXX::VEC3>& pos, VertexAttribute<typename XXX::VEC3>& pos2):
		FunctorAttribThreaded(),m_positions(pos),m_positions2(pos2)
Pierre Kraemer's avatar
merge..    
Pierre Kraemer committed
173
	{}
Sylvain Thery's avatar
Sylvain Thery committed
174

175
	void run(unsigned int i, unsigned int threadID)
Sylvain Thery's avatar
Sylvain Thery committed
176
	{
177
		m_positions2[i] = 1.1f * m_positions[i];
Sylvain Thery's avatar
Sylvain Thery committed
178
	}
179
	// no need to duplicate here functor can be shared (no data), call foreach with true parameter
180
};
Sylvain Thery's avatar
Sylvain Thery committed
181
182


183
184
185
void MyQT::threadAttrib()
{
	UnshrinkFunctor<PFP> funct(position,position2);
186
	Algo::Parallel::foreach_attrib(myMap.getAttributeContainer<VERTEX>(), funct);
187
188
189
190
191
192

	myMap.swapAttributes(position,position2);
	m_positionVBO->updateData(position);
	m_lines->setAttributePosition(m_positionVBO);
	updateGL();
}
Sylvain Thery's avatar
Sylvain Thery committed
193
194
195



196
197
198
//
// Simple thread that traverse a map
//
199
template <typename XXX>
200
class ShrinkFunctor : public FunctorMapThreaded<typename XXX::MAP >
Sylvain Thery's avatar
Sylvain Thery committed
201
202
{
protected:
203
204
	VertexAttribute<typename XXX::VEC3>& m_positions;
	VertexAttribute<typename XXX::VEC3>& m_positions2;
Sylvain Thery's avatar
Sylvain Thery committed
205
public:
206
207
208
209
	ShrinkFunctor( typename XXX::MAP& map, VertexAttribute<typename XXX::VEC3>& pos, VertexAttribute<typename XXX::VEC3>& pos2):
		FunctorMapThreaded< typename XXX::MAP>(map),
		m_positions(pos),m_positions2(pos2)
	{}
210

211
	void run(Dart d, unsigned int threadID)
212
	{
213
214
215
216
217
218
219
220
221
		typename XXX::VEC3 Q(0,0,0);
		int nb=0;
		Traversor2VVaE<typename XXX::MAP> trav(this->m_map,d);
		for (Dart e=trav.begin(); e!=trav.end(); e = trav.next())
		{
			Q += m_positions[e];
			nb++;
		}
		m_positions2[d] = Q/nb;
222
	}
223
	// no need to duplicate here functor can be shared (no data), call foreach with true parameter
Sylvain Thery's avatar
Sylvain Thery committed
224
225
226
};


227
228
229
void MyQT::threadSimple()
{
	ShrinkFunctor<PFP> funct(myMap,position,position2);
230
	Algo::Parallel::foreach_cell<PFP::MAP,VERTEX>(myMap, funct);
231
232
233
234
235
236
237
238
239
240
241
242
243
244

	myMap.swapAttributes(position,position2);
	m_positionVBO->updateData(position);
	m_lines->setAttributePosition(m_positionVBO);
	updateGL();
}






// Thread foreach with storage (computing average length of edges)

245
template <typename XXX>
246
class LengthEdgeFunctor : public FunctorMapThreaded<typename XXX::MAP >
Sylvain Thery's avatar
Sylvain Thery committed
247
{
248
protected:
249
	VertexAttribute<typename XXX::VEC3>& m_positions;
250
251
252
	double m_length;
	unsigned int m_nb;
public:
253
254
255
256
257
258
259
260
	LengthEdgeFunctor( typename XXX::MAP& map, VertexAttribute<typename XXX::VEC3>& pos):
		FunctorMapThreaded< typename XXX::MAP>(map),
		m_positions(pos), m_length(0.0), m_nb(0)
	{}

	double getLength() { return m_length;}

	unsigned int getNb() { return m_nb;}
261

262
	void run(Dart d, unsigned int threadID)
263
264
265
266
267
268
269
	{
		Dart dd = this->m_map.phi2(d);
		typename XXX::VEC3 V = m_positions[dd] - m_positions[d];
		m_length += V.norm();
		m_nb++;
	}

270
271
272
273
274
275
276
277
278
279
	// no need to duplicate here, we create 1 functor by thread (see bellow)
};

void MyQT::threadStorage()
{
	// functor need storage so we need one per thread
	std::vector<FunctorMapThreaded<PFP::MAP>*> functs;
	unsigned int nbthreads = Algo::Parallel::optimalNbThreads();

	for (unsigned int i=0; i<nbthreads; ++i)
280
	{
281
282
		LengthEdgeFunctor<PFP>* lef = new LengthEdgeFunctor<PFP>(myMap,position);
		functs.push_back(lef);
283
284
	}

285
286
	CGoGNout << "using "<< nbthreads << " threads"<< CGoGNendl;
	Algo::Parallel::foreach_cell<PFP::MAP,EDGE>(myMap, functs, nbthreads);
287

288
289
290
291
292
293
294
295
296
297
298
	//compute average length from each thread result and delete functors
	double average = 0;
	unsigned int all = 0;
	for (unsigned int i=0; i<nbthreads; ++i)
	{
		LengthEdgeFunctor<PFP>* lef = dynamic_cast<LengthEdgeFunctor<PFP>*>(functs[i]);
		average += lef->getLength();
		all += lef->getNb();
		delete lef;
	}
	average /= all;
Sylvain Thery's avatar
Sylvain Thery committed
299

300
	CGoGNout << "AVERAGE LENGTH "<< average << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
301

302
303
304
305
306
307
308
309
310
}


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

Sylvain Thery's avatar
Sylvain Thery committed
311

312
313
 	sqt.statusMsg("Neww to create a sphere or Load for a mesh file");
 	CGoGNStream::allToConsole(&sqt);
Sylvain Thery's avatar
Sylvain Thery committed
314

315
316
317
318
319
320
321
322
323
 	if (!position.isValid())
 		position = myMap.addAttribute<PFP::VEC3, VERTEX>("position");

	if (!position2.isValid())
 		position2 = myMap.addAttribute<PFP::VEC3, VERTEX>("position2");

	if (!normal.isValid())
 		normal = myMap.addAttribute<PFP::VEC3, VERTEX>("normal");

324
325
326
	unsigned int nbt = 64;
	if (argc==2)
		nbt = atoi(argv[1]);
327
328
 		// create a sphere
 	Algo::Modelisation::Polyhedron<PFP> prim(myMap, position);
329
 	prim.cylinder_topo(nbt,nbt, true, true);
330
331
332
333
334
335
336
 	prim.embedSphere(20.0f);


   //  bounding box
	Geom::BoundingBox<PFP::VEC3> bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position);
	float lWidthObj = std::max<PFP::REAL>(std::max<PFP::REAL>(bb.size(0), bb.size(1)), bb.size(2));
	Geom::Vec3f lPosObj = (bb.min() +  bb.max()) / PFP::REAL(2);
337
338
	CGoGNout << "lPosObj=" << lPosObj << CGoGNendl;
	CGoGNout << "lWidthObj=" << lWidthObj << CGoGNendl;
339
340
341
342
343
344
	sqt.setParamObject(lWidthObj,lPosObj.data());

//	myMap.enableQuickTraversal<EDGE>() ;
//	myMap.enableQuickTraversal<VERTEX>() ;

	sqt.show();
Sylvain Thery's avatar
Sylvain Thery committed
345

Sylvain Thery's avatar
Sylvain Thery committed
346

347
	return app.exec();
Sylvain Thery's avatar
Sylvain Thery committed
348
}