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
}