Coupure prévue mardi 3 Août au matin pour maintenance du serveur. Nous faisons au mieux pour que celle-ci soit la plus brève possible.

tuto_mt.cpp 9.63 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
43
#include "Algo/Parallel/cgogn_thread.h"
#include "Utils/chrono.h"
Sylvain Thery's avatar
Sylvain Thery committed
44
45
46
47
48
49
50
51
52
53

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
54
	typedef EmbeddedMap2 MAP;
Sylvain Thery's avatar
Sylvain Thery committed
55
56
};

57

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

Sylvain Thery's avatar
Sylvain Thery committed
63

64

Sylvain Thery's avatar
Sylvain Thery committed
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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());
	}
};
84
85
86



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

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

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

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

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


105
106
107
108
109
	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));
110

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


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

118
119
120
121
122
123
	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
124

125
}
Sylvain Thery's avatar
Sylvain Thery committed
126

127
128
void MyQT::cb_redraw()
{
129
130
	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
131
132
133
}


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

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

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


159
160
161
162

//
// Simple attribute parallel functor and traversor
//
163
template <typename XXX>
164
class UnshrinkFunctor : public FunctorAttribThreaded
Sylvain Thery's avatar
Sylvain Thery committed
165
166
{
protected:
167
168
	VertexAttribute<typename XXX::VEC3>& m_positions;
	VertexAttribute<typename XXX::VEC3>& m_positions2;
Sylvain Thery's avatar
Sylvain Thery committed
169
public:
170
171
	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
172
	{}
Sylvain Thery's avatar
Sylvain Thery committed
173

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


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

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



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

210
	void run(Dart d, unsigned int threadID)
211
	{
212
213
214
215
216
217
218
219
220
		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;
221
	}
222
	// no need to duplicate here functor can be shared (no data), call foreach with true parameter
Sylvain Thery's avatar
Sylvain Thery committed
223
224
225
};


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

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






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

244
template <typename XXX>
245
class LengthEdgeFunctor : public FunctorMapThreaded<typename XXX::MAP >
Sylvain Thery's avatar
Sylvain Thery committed
246
{
247
protected:
248
	VertexAttribute<typename XXX::VEC3>& m_positions;
249
250
251
	double m_length;
	unsigned int m_nb;
public:
252
253
254
255
256
257
258
259
	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;}
260

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

269
270
271
272
273
274
275
276
277
278
	// 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)
279
	{
280
281
		LengthEdgeFunctor<PFP>* lef = new LengthEdgeFunctor<PFP>(myMap,position);
		functs.push_back(lef);
282
283
284
	}


285
	Algo::Parallel::foreach_cell<PFP::MAP,EDGE>(myMap, functs, 4);
286

287
288
289
290
291
292
293
294
295
296
297
	//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
298

299
	std::cout << "AVERAGE LENGTH "<< average << std::endl;
Sylvain Thery's avatar
Sylvain Thery committed
300

301
302
303
304
305
306
307
308
309
}


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

Sylvain Thery's avatar
Sylvain Thery committed
310

311
312
 	sqt.statusMsg("Neww to create a sphere or Load for a mesh file");
 	CGoGNStream::allToConsole(&sqt);
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
333
334
335
336
337
338
339
340
341
 	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");

 		// create a sphere
 	Algo::Modelisation::Polyhedron<PFP> prim(myMap, position);
// 	prim.cylinder_topo(2640,2640, true, true); // test for speed timing
 	prim.cylinder_topo(64,64, true, true); // topo of sphere is a closed cylinder
 	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);
	std::cout << "lPosObj=" << lPosObj << std::endl;
	std::cout << "lWidthObj=" << lWidthObj << std::endl;
	sqt.setParamObject(lWidthObj,lPosObj.data());

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

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

Sylvain Thery's avatar
Sylvain Thery committed
343

344
	return app.exec();
Sylvain Thery's avatar
Sylvain Thery committed
345
}