diff --git a/Apps/Examples/volumeExplorer.cpp b/Apps/Examples/volumeExplorer.cpp index cfc9e63af7883111fa2f41000c57042a6818917c..357b265a5c79fd394e3f1be13fcc14f5a3e5a95e 100644 --- a/Apps/Examples/volumeExplorer.cpp +++ b/Apps/Examples/volumeExplorer.cpp @@ -31,6 +31,8 @@ #include "Algo/Import/import.h" #include "Algo/Geometry/volume.h" +#include "Utils/chrono.h" + PFP::MAP myMap; VertexAttribute position ; @@ -128,6 +130,82 @@ void MyQT::slider_released() } +void MyQT::cb_Open() +{ + std::string filters("all (*.*);; trian (*.trian);; ctm (*.ctm);; off (*.off);; ply (*.ply)") ; + std::string filename = selectFile("Open Mesh", "", filters) ; + if (filename.empty()) + return ; + + myMap.clear(true); + + std::vector attrNames ; + + size_t pos = filename.rfind("."); // position of "." in filename + std::string extension = filename.substr(pos); + + if(extension == std::string(".tet")) + { + if(!Algo::Import::importTet(myMap,filename,attrNames)) + { + CGoGNerr << "could not import " << filename << CGoGNendl ; + return; + } + else + position = myMap.getAttribute(attrNames[0]) ; + } + + if(extension == std::string(".node")) + { + if(!Algo::Import::importMeshV(myMap, filename, attrNames, Algo::Import::ImportVolumique::NODE)) + { + std::cerr << "could not import " << filename << std::endl ; + return ; + } + else + position = myMap.getAttribute(attrNames[0]) ; + } + + + if(extension == std::string(".off")) + { + if(!Algo::Import::importMeshToExtrude(myMap, filename, attrNames)) + { + std::cerr << "could not import " << filename << std::endl ; + return ; + } + else + { + position = myMap.getAttribute(attrNames[0]) ; + myMap.closeMap(); + } + } + + color = myMap.addAttribute("color"); + + TraversorCell tra(myMap); + float maxV = 0.0f; + for (Dart d = tra.begin(); d != tra.end(); d = tra.next()) + { + float v = Algo::Geometry::tetrahedronVolume(myMap, d, position); + color[d] = PFP::VEC3(v,0,0); + if (v>maxV) + maxV=v; + } + for (unsigned int i = color.begin(); i != color.end(); color.next(i)) + { + color[i][0] /= maxV; + color[i][2] = 1.0f - color[i][0]; + } + + SelectorDartNoBoundary nb(myMap); + m_topo_render->updateData(myMap, position, 0.8f, 0.8f, 0.8f, nb); + m_explode_render->updateData(myMap, position, color); + + updateGL() ; +} + + void MyQT::cb_initGL() { // choose to use GL version 2 @@ -415,6 +493,24 @@ int main(int argc, char **argv) dock.slider_explode_face->setValue(80); sqt.clipping_onoff(true); + Utils::Chrono ch; + + std::cout << "Compute Volume ->"<< std::endl; + ch.start(); + float vol = Algo::Geometry::totalVolume(myMap, position); + vol += Algo::Geometry::totalVolume(myMap, position); + vol += Algo::Geometry::totalVolume(myMap, position); + vol += Algo::Geometry::totalVolume(myMap, position); + std::cout << ch.elapsed()<< " ms val="<(myMap, position); + vol += Algo::Geometry::Parallel::totalVolume(myMap, position); + vol += Algo::Geometry::Parallel::totalVolume(myMap, position); + vol += Algo::Geometry::Parallel::totalVolume(myMap, position); + std::cout << ch.elapsed()<< " ms // val="<(VERTEX+m_second2, m_drawer, myMap, m_selected, position, m_expl); m_drawer.color3f(1.0f,0.0f,0.0f); - Traversor* tra = Traversor::createIncident(myMap, m_selected, 2, VERTEX+m_second2, VERTEX+m_first2); + Traversor* tra = TraversorFactory::createIncident(myMap, m_selected, 2, VERTEX+m_second2, VERTEX+m_first2); for (Dart d=tra->begin(); d != tra->end(); d= tra->next()) m_affDarts.push_back(d); Algo::Render::drawerCells(VERTEX+m_first2, m_drawer, myMap, m_affDarts, position, m_expl); @@ -223,7 +221,7 @@ void MyQT::traverse2() { Algo::Render::drawerCell(VERTEX+m_first2, m_drawer, myMap, m_selected, position, m_expl); m_drawer.color3f(1.0f,0.0f,0.0f); - Traversor* tra = Traversor::createAdjacent(myMap, m_selected, 2, VERTEX+m_first2, VERTEX+m_second2); + Traversor* tra = TraversorFactory::createAdjacent(myMap, m_selected, 2, VERTEX+m_first2, VERTEX+m_second2); for (Dart d = tra->begin(); d != tra->end(); d = tra->next()) m_affDarts.push_back(d); Algo::Render::drawerCells(VERTEX+m_first2, m_drawer, myMap, m_affDarts, position, m_expl); @@ -286,7 +284,7 @@ void MyQT::traverse3() dynamicMarkOrbit(VERTEX+m_second3); m_drawer.color3f(1.0f,0.0f,0.0f); - Traversor* tra = Traversor::createIncident(myMap,m_selected, 3, VERTEX+m_second3, VERTEX+m_first3); + Traversor* tra = TraversorFactory::createIncident(myMap,m_selected, 3, VERTEX+m_second3, VERTEX+m_first3); for (Dart d = tra->begin(); d != tra->end(); d = tra->next()) { m_affDarts.push_back(d); @@ -306,7 +304,7 @@ void MyQT::traverse3() dynamicMarkOrbit(VERTEX+m_first3); m_drawer.color3f(1.0f,0.0f,0.0f); - Traversor* tra = Traversor::createAdjacent(myMap,m_selected, 3, VERTEX+m_first3, VERTEX+m_second3); + Traversor* tra = TraversorFactory::createAdjacent(myMap,m_selected, 3, VERTEX+m_first3, VERTEX+m_second3); for (Dart d = tra->begin(); d != tra->end(); d = tra->next()) { m_affDarts.push_back(d); diff --git a/Apps/Tuto/tuto_mt.cpp b/Apps/Tuto/tuto_mt.cpp index 91f1e3b47b6953b7f852034b0aabbc6fba23eeb0..f1d66cce6589744c0513044f3a693aae38caf148 100644 --- a/Apps/Tuto/tuto_mt.cpp +++ b/Apps/Tuto/tuto_mt.cpp @@ -33,16 +33,15 @@ #include "Algo/Import/import.h" #include "Algo/Geometry/boundingbox.h" -#include "Algo/Render/GL1/map_glRender.h" #include "Utils/GLSLShader.h" -#include "Algo/Geometry/area.h" +//#include "Algo/Geometry/area.h" #include "Algo/Geometry/normal.h" #include "Algo/Modelisation/polyhedron.h" #include "Algo/Parallel/parallel_foreach.h" - -// for file input -#include "Utils/qtInputs.h" +#include "Algo/Parallel/cgogn_thread.h" +#include "Utils/cgognStream.h" +#include "Utils/chrono.h" using namespace CGoGN ; @@ -56,312 +55,249 @@ struct PFP: public PFP_STANDARD typedef EmbeddedMap2 MAP; }; -// declaration of the map -PFP::MAP myMap; -// attribute handlers +PFP::MAP myMap; VertexAttribute position; +VertexAttribute position2; VertexAttribute normal; -// open file -void MyQT::cb_Open() -{ - // set some filters -// std::string filters("all (*.*);; trian (*.trian);; ctm (*.ctm);; off (*.off);; ply (*.ply)"); -// -// std::string filename = selectFile("OpenMesh","",filters); -// -// std::vector attrNames ; -// if(!Algo::Import::importMesh(myMap, filename.c_str(), attrNames)) -// { -// CGoGNerr << "could not import " << filename << CGoGNendl ; -// return; -// } - - std::vector attrNames ; - if(!Algo::Import::importMesh(myMap, "/home/thery/Data/liver.trian", attrNames)) - { - CGoGNerr << "could not import xxx" << CGoGNendl ; - return; - } - // recuper l'attribut pour la position des points (créé lors de l'import) - position = myMap.getAttribute(attrNames[0]) ; - if (!normal.isValid()) - normal = myMap.addAttribute("normal"); - Algo::Geometry::computeNormalVertices(myMap, position, normal) ; +template +class ThreadNormals: public Algo::Parallel::CGoGNThread +{ +protected: + VertexAttribute& m_positions; + VertexAttribute& m_normals; +public: + ThreadNormals(typename XXX::MAP& map, VertexAttribute& pos, VertexAttribute& norm, unsigned int th): + Algo::Parallel::CGoGNThread(map,th), + m_positions(pos), + m_normals(norm) + {} + + void operator()() + { + Algo::Geometry::computeNormalVertices(this->m_map, m_positions, m_normals, SelectorTrue(), this->tid()); + } +}; - // bounding box - Geom::BoundingBox bb = Algo::Geometry::computeBoundingBox(myMap, position); - float lWidthObj = std::max(std::max(bb.size(0), bb.size(1)), bb.size(2)); - Geom::Vec3f lPosObj = (bb.min() + bb.max()) / PFP::REAL(2); - // envoit info BB a l'interface - setParamObject(lWidthObj,lPosObj.data()); - updateGLMatrices(); -} -// new -void MyQT::cb_New() +void MyQT::cb_initGL() { - if (!position.isValid()) - position = myMap.addAttribute("position"); + Utils::GLSLShader::setCurrentOGLVersion(2); - // create a sphere - Algo::Modelisation::Polyhedron prim(myMap, position); - prim.cylinder_topo(16,16, true, true); // topo of sphere is a closed cylinder - prim.embedSphere(10.0f); + // create the render + m_render = new Algo::Render::GL2::MapRender(); - if (!normal.isValid()) - normal = myMap.addAttribute("normal"); + // create VBO for position + m_positionVBO = new Utils::VBO(); + m_positionVBO->updateData(position); - Algo::Geometry::computeNormalVertices(myMap, position, normal) ; + m_normalVBO = new Utils::VBO(); - // bounding box - Geom::BoundingBox bb = Algo::Geometry::computeBoundingBox(myMap, position); - float lWidthObj = std::max(std::max(bb.size(0), bb.size(1)), bb.size(2)); - Geom::Vec3f lPosObj = (bb.min() + bb.max()) / PFP::REAL(2); + m_shader = new Utils::ShaderSimpleColor(); + m_shader->setAttributePosition(m_positionVBO); + m_shader->setColor(Geom::Vec4f(1.,1.,0.,0.)); - setParamObject(lWidthObj,lPosObj.data()); - updateGLMatrices(); -} + 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)); + + CGoGNout << "Je calcule les normales en meme temps que les primitives" << CGoGNendl; + boost::thread thread1( ThreadNormals(myMap,position,normal,1)); -void MyQT::cb_initGL() -{ - // Old school openGL ;) - Utils::GLSLShader::setCurrentOGLVersion(1); - glewInit(); + m_render->initPrimitives(myMap, allDarts, Algo::Render::GL2::LINES); + m_render->initPrimitives(myMap, allDarts, Algo::Render::GL2::POINTS); - // init lighting parameters - float lightPosition[4]= {10.0f,10.0f,10000.0f,1.0f}; - float lightColor[4]= {0.9f,0.9f,0.9f,1.0f}; + registerShader(m_shader); + registerShader(m_lines); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - glEnable(GL_LIGHT0); - glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); - glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); - glEnable(GL_NORMALIZE); -// glDisable(GL_CULL_FACE); -// glFrontFace(GL_CCW); + // on attend la fin du thread pour etre sur que normal est a jour + thread1.join(); + m_normalVBO->updateData(normal); } void MyQT::cb_redraw() { - GLfloat diff[4]= {0.0f,1.0f,0.1f,1.0f}; - GLfloat amb[4]= {0.1f,0.0f,0.1f,1.0f}; - GLfloat spec[4]= {1.0f,1.0f,1.0f,1.0f}; - float shininess=125.0f; - - // draw the lines -// glDisable(GL_LIGHTING); -// glColor3f(0.0f, 0.0f, 0.3f); -// glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); -// glDisable(GL_LIGHTING); -// -// Algo::Render::GL1::renderTriQuadPoly(myMap,Algo::Render::GL1::LINE, 1.0f,position, normal); - - // draw the faces - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0f, 1.0f); - glEnable(GL_LIGHTING); - glEnable(GL_SMOOTH); - glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); - - glMaterialfv(GL_FRONT, GL_DIFFUSE, diff); - glMaterialfv(GL_FRONT, GL_AMBIENT, amb); - glMaterialfv(GL_FRONT,GL_SPECULAR,spec); - glMaterialf( GL_FRONT, GL_SHININESS, shininess); - Algo::Render::GL1::renderTriQuadPoly(myMap,Algo::Render::GL1::SMOOTH, 1.0f,position, normal); - glDisable(GL_POLYGON_OFFSET_FILL); + m_render->draw(m_shader, Algo::Render::GL2::LINES); + m_render->draw(m_lines, Algo::Render::GL2::POINTS); } -template -class ThreadArea: public Algo::Parallel::CGoGNThread +void MyQT::cb_keyPress(int code) { -protected: - const typename XXX::TVEC3& m_positions; - float area; -public: - ThreadArea(typename XXX::MAP& map, const typename XXX::TVEC3& pos, unsigned int th) : - Algo::Parallel::CGoGNThread(map,th), - m_positions(pos), - area(0.0f) - {} + Utils::Chrono ch; + ch.start(); - void operator()() + switch(code) { - // 3 times just for fun !!! - area += Algo::Geometry::totalArea(this->m_map, m_positions, SelectorTrue(), this->m_threadId); - area += Algo::Geometry::totalArea(this->m_map, m_positions, SelectorTrue(), this->m_threadId); - area += Algo::Geometry::totalArea(this->m_map, m_positions, SelectorTrue(), this->m_threadId); + case 'a': + threadSimple(); + break; + case 'z': + threadStorage(); + break; + case 'q': + threadAttrib(); + break; + default: + break; } + CGoGNout << "time = "<< ch.elapsed() << CGoGNendl; + + updateGL(); +} - float getTripleValue() { return area; } -}; +// +// Simple attribute parallel functor and traversor +// template -class ThreadNormals: public Algo::Parallel::CGoGNThread +class UnshrinkFunctor : public FunctorAttribThreaded { protected: - const typename XXX::TVEC3& m_positions; - typename XXX::TVEC3& m_normals; + VertexAttribute& m_positions; + VertexAttribute& m_positions2; public: - ThreadNormals(typename XXX::MAP& map, const typename XXX::TVEC3& pos, typename XXX::TVEC3& norm, unsigned int th): - Algo::Parallel::CGoGNThread(map,th), - m_positions(pos), - m_normals(norm) + UnshrinkFunctor( VertexAttribute& pos, VertexAttribute& pos2): + FunctorAttribThreaded(),m_positions(pos),m_positions2(pos2) {} - void operator()() + void run(unsigned int i, unsigned int threadID) { - Algo::Geometry::computeNormalVertices(this->m_map, m_positions, m_normals, SelectorTrue(), this->m_threadId); + m_positions2[i] = 1.1f * m_positions[i]; } - }; -//template -//class Thread0 -//{ -//protected: -// typename XXX::MAP& m_map; -// MyGlutWin& m_mgw; -// unsigned int m_th; -// SelectorTrue m_selt; -//public: -// Thread0(typename XXX::MAP& map,MyGlutWin& mgw, unsigned int th): -// m_map(map), m_mgw(mgw), m_th(th) {} -// -// void operator()() -// { -// CGoGNout << "Begin render init"<updateData(Algo::Render::VBO::POSITIONS, position); -// -// m_mgw.m_render->initPrimitives(m_map, m_selt, Algo::Render::VBO::TRIANGLES,m_th); -// m_mgw.m_render->initPrimitives(m_map, m_selt, Algo::Render::VBO::LINES,m_th); -// -// m_mgw.releaseContext(); -// CGoGNout<< "Render OK "<< CGoGNendl; -// -// } -//}; +void MyQT::threadAttrib() +{ + UnshrinkFunctor funct(position,position2); + Algo::Parallel::foreach_attrib(myMap.getAttributeContainer(), funct); + + myMap.swapAttributes(position,position2); + m_positionVBO->updateData(position); + m_lines->setAttributePosition(m_positionVBO); + updateGL(); +} +// +// Simple thread that traverse a map +// template -class calculFunctor1 : public Algo::Parallel::FunctorMapThreaded +class ShrinkFunctor : public FunctorMapThreaded { protected: - typename XXX::TVEC3& m_positions; - typename XXX::TVEC3& m_normals; + VertexAttribute& m_positions; + VertexAttribute& m_positions2; public: - calculFunctor1( typename XXX::MAP& map, typename XXX::TVEC3& pos, typename XXX::TVEC3& norm, unsigned int id=0): - Algo::Parallel::FunctorMapThreaded(map,id), m_positions(pos), m_normals(norm) {} - - bool operator()(Dart d) - { - typename XXX::VEC3 n1 = Algo::Geometry::vertexNormal(this->m_map, d, m_positions); - typename XXX::VEC3 n2 = Algo::Geometry::vertexNormal(this->m_map, this->m_map.phi1(d), m_positions); - typename XXX::VEC3 n3 = Algo::Geometry::vertexNormal(this->m_map, this->m_map.phi_1(d), m_positions); - typename XXX::VEC3 n = n1+n2+n3; - n1 = Algo::Geometry::vertexNormal(this->m_map, d, m_positions); - n2 = Algo::Geometry::vertexNormal(this->m_map, this->m_map.phi1(d), m_positions); - n3 = Algo::Geometry::vertexNormal(this->m_map, this->m_map.phi_1(d), m_positions); - n += n1+n2+n3; - n.normalize(); - m_normals[d] = n; -// m_normals[d] = Algo::Geometry::vertexNormal(this->m_map, d, m_positions); - return false; - } + ShrinkFunctor( typename XXX::MAP& map, VertexAttribute& pos, VertexAttribute& pos2): + FunctorMapThreaded< typename XXX::MAP>(map), + m_positions(pos),m_positions2(pos2) + {} - Algo::Parallel::FunctorMapThreaded* duplicate(unsigned int id) + void run(Dart d, unsigned int threadID) { - calculFunctor1* copy = new calculFunctor1(this->m_map,m_positions,m_normals,id); - return reinterpret_cast*>(copy); + typename XXX::VEC3 Q(0,0,0); + int nb=0; + Traversor2VVaE 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; } + // no need to duplicate here functor can be shared (no data), call foreach with true parameter }; +void MyQT::threadSimple() +{ + ShrinkFunctor funct(myMap,position,position2); + Algo::Parallel::foreach_cell(myMap, funct); + + myMap.swapAttributes(position,position2); + m_positionVBO->updateData(position); + m_lines->setAttributePosition(m_positionVBO); + updateGL(); +} + + + + + + +// Thread foreach with storage (computing average length of edges) + template -class LengthEdgeFunctor : public Algo::Parallel::FunctorMapThreadedResult > +class LengthEdgeFunctor : public FunctorMapThreaded { protected: - typename XXX::TVEC3& m_positions; + VertexAttribute& m_positions; double m_length; unsigned int m_nb; public: - LengthEdgeFunctor( typename XXX::MAP& map, typename XXX::TVEC3& pos, unsigned int id=0): - Algo::Parallel::FunctorMapThreadedResult< typename XXX::MAP, std::pair >(map,id), - m_positions(pos), - m_length(0.0), - m_nb(0) {} + LengthEdgeFunctor( typename XXX::MAP& map, VertexAttribute& pos): + FunctorMapThreaded< typename XXX::MAP>(map), + m_positions(pos), m_length(0.0), m_nb(0) + {} - bool operator()(Dart d) + double getLength() { return m_length;} + + unsigned int getNb() { return m_nb;} + + void run(Dart d, unsigned int threadID) { Dart dd = this->m_map.phi2(d); typename XXX::VEC3 V = m_positions[dd] - m_positions[d]; m_length += V.norm(); m_nb++; - return false; - } - - Algo::Parallel::FunctorMapThreaded* duplicate(unsigned int id) - { - LengthEdgeFunctor* copy = new LengthEdgeFunctor(this->m_map,m_positions,id); - return reinterpret_cast*>(copy); } - std::pair getResult() { return std::pair(m_length,m_nb);} - + // no need to duplicate here, we create 1 functor by thread (see bellow) }; - -void MyQT::menu_slot1() +void MyQT::threadStorage() { - // cree un handler pour les normales aux sommets - VertexAttribute normal2 = myMap.addAttribute("normal2"); + // functor need storage so we need one per thread + std::vector*> functs; + unsigned int nbthreads = Algo::Parallel::optimalNbThreads(); - // ajout de 4 threads pour les markers - myMap.addThreadMarker(4); + for (unsigned int i=0; i* lef = new LengthEdgeFunctor(myMap,position); + functs.push_back(lef); + } - //Algorithmes en // + CGoGNout << "using "<< nbthreads << " threads"<< CGoGNendl; + Algo::Parallel::foreach_cell(myMap, functs); + + //compute average length from each thread result and delete functors + double average = 0; + unsigned int all = 0; + for (unsigned int i=0; i* lef = dynamic_cast*>(functs[i]); + average += lef->getLength(); + all += lef->getNb(); + delete lef; + } + average /= all; + + CGoGNout << "AVERAGE LENGTH "<< average << CGoGNendl; - boost::thread thread1( ThreadArea(myMap,position,1)); - boost::thread thread2( ThreadNormals(myMap,position,normal,2)); - thread1.join(); - thread2.join(); - - // parallelisation de boucle sans resultat - calculFunctor1 tf1(myMap,position,normal); - Algo::Parallel::foreach_orbit(myMap, VERTEX, tf1,4); - CGoGNout << "ok:"<< CGoGNendl; - - // parallelisation de boucle avec resultats stockes - - // vector pour le resultat (ici paire double/int pour faire la moyenne des longueurs des aretes) - std::vector > lengthp; - LengthEdgeFunctor tflef(myMap,position); // le foncteur - // on lance l'algo parallelise (4 threads, buffer de 16384 brins par thread) - Algo::Parallel::foreach_orbit_res< PFP,std::pair >(myMap, EDGE, tflef, 4 , 16384,lengthp); - // on calcule la somme des resultats - std::pair le = Algo::Parallel::sumPairResult(lengthp); - CGoGNout << "length :" <("position"); + + if (!position2.isValid()) + position2 = myMap.addAttribute("position2"); + + if (!normal.isValid()) + normal = myMap.addAttribute("normal"); + + unsigned int nbt = 64; + if (argc==2) + nbt = atoi(argv[1]); + // create a sphere + Algo::Modelisation::Polyhedron prim(myMap, position); + prim.cylinder_topo(nbt,nbt, true, true); + prim.embedSphere(20.0f); + + + // bounding box + Geom::BoundingBox bb = Algo::Geometry::computeBoundingBox(myMap, position); + float lWidthObj = std::max(std::max(bb.size(0), bb.size(1)), bb.size(2)); + Geom::Vec3f lPosObj = (bb.min() + bb.max()) / PFP::REAL(2); + CGoGNout << "lPosObj=" << lPosObj << CGoGNendl; + CGoGNout << "lWidthObj=" << lWidthObj << CGoGNendl; + sqt.setParamObject(lWidthObj,lPosObj.data()); + +// myMap.enableQuickTraversal() ; +// myMap.enableQuickTraversal() ; + + sqt.show(); -// int xx = 3; -// double yy = 2.5; -// bool zz=true; -// int kk=32; -// int cc=2; -// -// { -// using namespace CGoGN::Utils::QT; -// -// inputValues( VarInteger(0,20,xx, "Entier", -// VarBool(zz, "Bool", -// VarDbl(0.314,3.14,yy,"Double", -// VarSlider(10,100,kk,"Slider", -// VarCombo("Riri;Fifi;Loulou;Donald",cc,"Combo") ))))); -// } -// -// std::cout << "Int:" << xx << " Bool:"< -#include "Utils/Qt/qtSimple.h" + +#include "Topology/generic/parameters.h" +#include "Topology/map/embeddedMap3.h" + +#include "Geometry/vector_gen.h" +#include "Algo/Geometry/boundingbox.h" +#include "Algo/Render/GL2/mapRender.h" + +#include "Utils/Shaders/shaderSimpleColor.h" +#include "Utils/Shaders/shaderVectorPerVertex.h" #include "Utils/cgognStream.h" +#include "Utils/Qt/qtSimple.h" + + // forward definitions (minimize includes) namespace CGoGN { namespace Algo { namespace Render { namespace GL1 { class MapRender; } } } } @@ -45,21 +57,67 @@ class MyQT: public Utils::QT::SimpleQT Q_OBJECT public: - MyQT() + Algo::Render::GL2::MapRender* m_render; + + Utils::VBO* m_positionVBO; + Utils::VBO* m_normalVBO; + + Utils::ShaderSimpleColor* m_shader; + Utils::ShaderVectorPerVertex* m_lines; + + + + MyQT(): + m_render(NULL), + m_positionVBO(NULL), + m_normalVBO(NULL), + m_shader(NULL), + m_lines(NULL) {} - // callbacks of simpleQT to overdefine: +protected: + void cb_redraw(); void cb_initGL(); - void cb_Open(); + void threadSimple(); + + void threadAttrib(); + + void threadStorage(); - void cb_New(); + void cb_keyPress(int code); -// callbacks (slots) locally defined -public slots: - void menu_slot1(); }; + + + + + + + +//class MyQT: public Utils::QT::SimpleQT +//{ +// Q_OBJECT +// +//public: +// MyQT() +// {} +// +// // callbacks of simpleQT to overdefine: +// void cb_redraw(); +// +// void cb_initGL(); +// +// void cb_Open(); +// +// void cb_New(); +// +//// callbacks (slots) locally defined +//public slots: +// void menu_slot1(); +//}; + #endif diff --git a/Apps/Tuto/tuto_orbits.cpp b/Apps/Tuto/tuto_orbits.cpp index 02fed74e76c605cbc2cdba644f0b221ad9b71673..dddb0f25c20a07bb7c64c8542159c3a01bc82927 100644 --- a/Apps/Tuto/tuto_orbits.cpp +++ b/Apps/Tuto/tuto_orbits.cpp @@ -35,6 +35,7 @@ #include "Algo/Render/SVG/mapSVGRender.h" #include "Algo/Import/import.h" +#include "Topology/generic/traversorFactory.h" MAP myMap; VertexAttribute position ; @@ -66,7 +67,7 @@ void MyQT::orbit_list(int x) m_selected.clear(); // easy way to traverse darts of orbit - Traversor* tra = Traversor::createDartsOfOrbits(myMap,m_clicked,orbs[current_orbit]); + Traversor* tra = TraversorFactory::createDartsOfOrbits(myMap,m_clicked,orbs[current_orbit]); for (Dart e = tra->begin(); e != tra->end(); e = tra->next()) m_selected.push_back(e); } @@ -174,7 +175,7 @@ void MyQT::cb_mousePress(int button, int x, int y) m_selected.clear(); // easy way to traverse darts of orbit - Traversor* tra = Traversor::createDartsOfOrbits(myMap,m_clicked,orbs[current_orbit]); + Traversor* tra = TraversorFactory::createDartsOfOrbits(myMap,m_clicked,orbs[current_orbit]); for (Dart e = tra->begin(); e != tra->end(); e = tra->next()) m_selected.push_back(e); } diff --git a/include/Algo/Geometry/centroid.h b/include/Algo/Geometry/centroid.h index 74d8c8014058ae25b8f365b560c2c3a4c434d541..78538a6e0951c016a54a88526d10ac95a3afe9e7 100644 --- a/include/Algo/Geometry/centroid.h +++ b/include/Algo/Geometry/centroid.h @@ -49,7 +49,7 @@ namespace Geometry * @param attributs the vector of attribute or cell */ template -EMB volumeCentroidGen(typename PFP::MAP& map, Dart d, const EMBV& attributs); +EMB volumeCentroidGen(typename PFP::MAP& map, Dart d, const EMBV& attributs, unsigned int thread = 0); /** * Compute volume centroid @@ -59,9 +59,9 @@ EMB volumeCentroidGen(typename PFP::MAP& map, Dart d, const EMBV& attributs); * @param position the vector of attribute */ template -typename PFP::VEC3 volumeCentroid(typename PFP::MAP& map, Dart d, const VertexAttribute& position) +typename PFP::VEC3 volumeCentroid(typename PFP::MAP& map, Dart d, const VertexAttribute& position, unsigned int thread = 0) { - return volumeCentroidGen, typename PFP::VEC3>(map, d, position); + return volumeCentroidGen, typename PFP::VEC3>(map, d, position, thread); } /** @@ -116,13 +116,38 @@ typename PFP::VEC3 vertexNeighborhoodCentroid(typename PFP::MAP& map, Dart d, co } template -void computeCentroidVolumes(typename PFP::MAP& map, const VertexAttribute& position, VolumeAttribute& vol_centroid, const FunctorSelect& select = allDarts) ; +void computeCentroidVolumes(typename PFP::MAP& map, + const VertexAttribute& position, VolumeAttribute& vol_centroid, + const FunctorSelect& select = allDarts, unsigned int thread = 0) ; template -void computeCentroidFaces(typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& face_centroid, const FunctorSelect& select = allDarts) ; +void computeCentroidFaces(typename PFP::MAP& map, + const VertexAttribute& position, FaceAttribute& face_centroid, + const FunctorSelect& select = allDarts, unsigned int thread = 0) ; template -void computeNeighborhoodCentroidVertices(typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& vertex_centroid, const FunctorSelect& select = allDarts) ; +void computeNeighborhoodCentroidVertices(typename PFP::MAP& map, + const VertexAttribute& position, VertexAttribute& vertex_centroid, + const FunctorSelect& select = allDarts, unsigned int thread = 0) ; + + +namespace Parallel +{ +template +void computeCentroidVolumes(typename PFP::MAP& map, + const VertexAttribute& position, VolumeAttribute& vol_centroid, + const FunctorSelect& select = allDarts, unsigned int nbth = 0, unsigned int current_thread = 0) ; + +template +void computeCentroidFaces(typename PFP::MAP& map, + const VertexAttribute& position, FaceAttribute& face_centroid, + const FunctorSelect& select = allDarts, unsigned int nbth = 0, unsigned int current_thread = 0) ; + +template +void computeNeighborhoodCentroidVertices(typename PFP::MAP& map, + const VertexAttribute& position, VertexAttribute& vertex_centroid, + const FunctorSelect& select = allDarts, unsigned int nbth = 0, unsigned int current_thread = 0) ; +} } // namespace Geometry diff --git a/include/Algo/Geometry/centroid.hpp b/include/Algo/Geometry/centroid.hpp index bdb9cef53698fb4b62ed708f3bdf70563efdc886..f3c9b10a87238d520385a4a94a7390cbb5cf6657 100644 --- a/include/Algo/Geometry/centroid.hpp +++ b/include/Algo/Geometry/centroid.hpp @@ -27,6 +27,7 @@ #include "Topology/generic/cellmarker.h" #include "Topology/generic/traversorCell.h" #include "Topology/generic/traversor3.h" +#include "Algo/Parallel/parallel_foreach.h" namespace CGoGN @@ -39,12 +40,12 @@ namespace Geometry { template -EMB volumeCentroidGen(typename PFP::MAP& map, Dart d, const EMBV& attributs) +EMB volumeCentroidGen(typename PFP::MAP& map, Dart d, const EMBV& attributs, unsigned int thread) { EMB center = AttribOps::zero() ; unsigned int count = 0 ; - Traversor3WV tra(map,d); + Traversor3WV tra(map,d,false,thread); for (Dart d = tra.begin(); d != tra.end(); d = tra.next()) { center += attributs[d]; @@ -86,29 +87,126 @@ EMB vertexNeighborhoodCentroidGen(typename PFP::MAP& map, Dart d, const EMBV& at } template -void computeCentroidVolumes(typename PFP::MAP& map, const VertexAttribute& position, VolumeAttribute& vol_centroid, const FunctorSelect& select) +void computeCentroidVolumes(typename PFP::MAP& map, const VertexAttribute& position, VolumeAttribute& vol_centroid, const FunctorSelect& select, unsigned int thread) { - TraversorW t(map, select) ; + TraversorW t(map, select,thread) ; for(Dart d = t.begin(); d != t.end(); d = t.next()) - vol_centroid[d] = volumeCentroid(map, d, position) ; + vol_centroid[d] = volumeCentroid(map, d, position,thread) ; } template -void computeCentroidFaces(typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& face_centroid, const FunctorSelect& select) +void computeCentroidFaces(typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& face_centroid, const FunctorSelect& select, unsigned int thread) { - TraversorF t(map, select) ; + TraversorF t(map, select,thread) ; for(Dart d = t.begin(); d != t.end(); d = t.next()) face_centroid[d] = faceCentroid(map, d, position) ; } template -void computeNeighborhoodCentroidVertices(typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& vertex_centroid, const FunctorSelect& select) +void computeNeighborhoodCentroidVertices(typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& vertex_centroid, const FunctorSelect& select, unsigned int thread) { - TraversorV t(map, select) ; + TraversorV t(map, select, thread) ; for(Dart d = t.begin(); d != t.end(); d = t.next()) vertex_centroid[d] = vertexNeighborhoodCentroid(map, d, position) ; } + + +namespace Parallel +{ +template +class FunctorComputeCentroidVolumes: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + VolumeAttribute& m_vol_centroid; +public: + FunctorComputeCentroidVolumes( typename PFP::MAP& map, const VertexAttribute& position, VolumeAttribute& vol_centroid): + FunctorMapThreaded(map), m_position(position), m_vol_centroid(vol_centroid) + { } + + void run(Dart d, unsigned int threadID) + { + m_vol_centroid[d] = volumeCentroid(this->m_map, d, m_position,threadID) ; + } +}; + + +template +void computeCentroidVolumes(typename PFP::MAP& map, + const VertexAttribute& position, VolumeAttribute& vol_centroid, + const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + FunctorComputeCentroidVolumes funct(map,position,vol_centroid); + Algo::Parallel::foreach_cell(map, funct, nbth, true, select, current_thread); +} + + +template +class FunctorComputeCentroidFaces: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + FaceAttribute& m_fcentroid; +public: + FunctorComputeCentroidFaces( typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& fcentroid): + FunctorMapThreaded(map), m_position(position), m_fcentroid(fcentroid) + { } + + void run(Dart d, unsigned int threadID) + { + m_fcentroid[d] = faceCentroid(this->m_map, d, m_position) ; + } +}; + + +template +void computeCentroidFaces(typename PFP::MAP& map, + const VertexAttribute& position, FaceAttribute& face_centroid, + const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + FunctorComputeCentroidFaces funct(map,position,face_centroid); + Algo::Parallel::foreach_cell(map, funct, nbth, false, select, current_thread); +} + + +template +class FunctorComputeNeighborhoodCentroidVertices: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + VertexAttribute& m_vcentroid; +public: + FunctorComputeNeighborhoodCentroidVertices( typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& vcentroid): + FunctorMapThreaded(map), m_position(position), m_vcentroid(vcentroid) + { } + + void run(Dart d, unsigned int threadID) + { + m_vcentroid[d] = vertexNeighborhoodCentroid(this->m_map, d, m_position) ; + } +}; + +template +void computeNeighborhoodCentroidVertices(typename PFP::MAP& map, + const VertexAttribute& position, VertexAttribute& vertex_centroid, + const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + FunctorComputeNeighborhoodCentroidVertices funct(map,position,vertex_centroid); + Algo::Parallel::foreach_cell(map, funct, nbth, false, select, current_thread); +} + +} + + + + + + + + + + + + + } // namespace Geometry } // namespace Algo diff --git a/include/Algo/Geometry/curvature.h b/include/Algo/Geometry/curvature.h index dce9d1e525f5410193310e7a7bf3f6bd927aa536..f4e7e8736a88db0ffea22544977148358fc5532e 100644 --- a/include/Algo/Geometry/curvature.h +++ b/include/Algo/Geometry/curvature.h @@ -101,7 +101,7 @@ void computeCurvatureVertices_NormalCycles( VertexAttribute& Kmax, VertexAttribute& Kmin, VertexAttribute& Knormal, - const FunctorSelect& select = allDarts) ; + const FunctorSelect& select = allDarts, unsigned int thread=0) ; template void computeCurvatureVertex_NormalCycles( @@ -115,7 +115,39 @@ void computeCurvatureVertex_NormalCycles( VertexAttribute& kmin, VertexAttribute& Kmax, VertexAttribute& Kmin, - VertexAttribute& Knormal) ; + VertexAttribute& Knormal, unsigned int thread=0) ; + + + +namespace Parallel +{ +template +void computeCurvatureVertices_NormalCycles( + typename PFP::MAP& map, + typename PFP::REAL radius, + const VertexAttribute& position, + const VertexAttribute& normal, + const EdgeAttribute& edgeangle, + VertexAttribute& kmax, + VertexAttribute& kmin, + VertexAttribute& Kmax, + VertexAttribute& Kmin, + VertexAttribute& Knormal, + const FunctorSelect& select = allDarts, unsigned int nbth = 0, unsigned int current_thread=0) ; + +template +void computeCurvatureVertices_QuadraticFitting( + typename PFP::MAP& map, + const VertexAttribute& position, + const VertexAttribute& normal, + VertexAttribute& kmax, + VertexAttribute& kmin, + VertexAttribute& Kmax, + VertexAttribute& Kmin, + const FunctorSelect& select = allDarts, unsigned int nbth=0, unsigned int current_thread=0); + +} // namespace Parallel + } // namespace Geometry diff --git a/include/Algo/Geometry/curvature.hpp b/include/Algo/Geometry/curvature.hpp index 7f6a70281855a8fc1bde28f9ef58f308015bfc50..6319102720eb7e54f624a17d5e0eb2b177beb7c5 100644 --- a/include/Algo/Geometry/curvature.hpp +++ b/include/Algo/Geometry/curvature.hpp @@ -289,11 +289,11 @@ void computeCurvatureVertices_NormalCycles( VertexAttribute& Kmax, VertexAttribute& Kmin, VertexAttribute& Knormal, - const FunctorSelect& select) + const FunctorSelect& select, unsigned int thread) { TraversorV t(map, select) ; for(Dart d = t.begin(); d != t.end(); d = t.next()) - computeCurvatureVertex_NormalCycles(map, d, radius, position, normal, edgeangle, kmax, kmin, Kmax, Kmin, Knormal) ; + computeCurvatureVertex_NormalCycles(map, d, radius, position, normal, edgeangle, kmax, kmin, Kmax, Kmin, Knormal,thread) ; } template @@ -308,12 +308,12 @@ void computeCurvatureVertex_NormalCycles( VertexAttribute& kmin, VertexAttribute& Kmax, VertexAttribute& Kmin, - VertexAttribute& Knormal) + VertexAttribute& Knormal, unsigned int thread) { typedef typename PFP::VEC3 VEC3 ; typedef typename PFP::REAL REAL ; - Algo::Selection::Collector_WithinSphere neigh(map, position, radius) ; + Algo::Selection::Collector_WithinSphere neigh(map, position, radius, thread) ; neigh.collectAll(dart) ; neigh.computeArea() ; @@ -379,6 +379,139 @@ void computeCurvatureVertex_NormalCycles( dirNormal *= -1; // change orientation } + +namespace Parallel +{ + +template +class FunctorComputeCurvatureVertices_NormalCycles: public FunctorMapThreaded +{ + typename PFP::REAL m_radius; + const VertexAttribute& m_position; + const VertexAttribute& m_normal; + const EdgeAttribute& m_edgeangle; + VertexAttribute& m_kmax; + VertexAttribute& m_kmin; + VertexAttribute& m_Kmax; + VertexAttribute& m_Kmin; + VertexAttribute& m_Knormal; +public: + FunctorComputeCurvatureVertices_NormalCycles( typename PFP::MAP& map, + typename PFP::REAL radius, + const VertexAttribute& position, + const VertexAttribute& normal, + const EdgeAttribute& edgeangle, + VertexAttribute& kmax, + VertexAttribute& kmin, + VertexAttribute& Kmax, + VertexAttribute& Kmin, + VertexAttribute& Knormal): + FunctorMapThreaded(map), + m_radius(radius), + m_position(position), + m_normal(normal), + m_edgeangle(edgeangle), + m_kmax(kmax), + m_kmin(kmin), + m_Kmax(Kmax), + m_Kmin(Kmin), + m_Knormal(Knormal) + { } + + void run(Dart d, unsigned int threadID) + { + computeCurvatureVertex_NormalCycles(this->m_map, d, m_radius, m_position, m_normal, m_edgeangle, m_kmax, m_kmin, m_Kmax, m_Kmin, m_Knormal, threadID) ; + } +}; + +template +void computeCurvatureVertices_NormalCycles( + typename PFP::MAP& map, + typename PFP::REAL radius, + const VertexAttribute& position, + const VertexAttribute& normal, + const EdgeAttribute& edgeangle, + VertexAttribute& kmax, + VertexAttribute& kmin, + VertexAttribute& Kmax, + VertexAttribute& Kmin, + VertexAttribute& Knormal, + const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + // WAHOO BIG PROBLEM WITH LAZZY EMBEDDING !!! + if (!map. template isOrbitEmbedded()) + { + CellMarkerNoUnmark cm(map); + map. template initOrbitEmbedding(); + } + if (!map. template isOrbitEmbedded()) + { + CellMarkerNoUnmark cm(map); + map. template initOrbitEmbedding(); + } + if (!map. template isOrbitEmbedded()) + { + CellMarkerNoUnmark cm(map); + map. template initOrbitEmbedding(); + } + + FunctorComputeCurvatureVertices_NormalCycles funct(map, radius, position, normal, edgeangle, kmax, kmin, Kmax, Kmin, Knormal); + Algo::Parallel::foreach_cell(map, funct, nbth, true, select, current_thread); +} + + + +template +class FunctorComputeCurvatureVertices_QuadraticFitting: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + const VertexAttribute& m_normal; + VertexAttribute& m_kmax; + VertexAttribute& m_kmin; + VertexAttribute& m_Kmax; + VertexAttribute& m_Kmin; +public: + FunctorComputeCurvatureVertices_QuadraticFitting( typename PFP::MAP& map, + const VertexAttribute& position, + const VertexAttribute& normal, + VertexAttribute& kmax, + VertexAttribute& kmin, + VertexAttribute& Kmax, + VertexAttribute& Kmin): + FunctorMapThreaded(map), + m_position(position), + m_normal(normal), + m_kmax(kmax), + m_kmin(kmin), + m_Kmax(Kmax), + m_Kmin(Kmin) + { } + + void run(Dart d, unsigned int threadID) + { + computeCurvatureVertex_QuadraticFitting(this->m_map, d, m_position, m_normal, m_kmax, m_kmin, m_Kmax, m_Kmin) ; + } +}; + + +template +void computeCurvatureVertices_QuadraticFitting( + typename PFP::MAP& map, + const VertexAttribute& position, + const VertexAttribute& normal, + VertexAttribute& kmax, + VertexAttribute& kmin, + VertexAttribute& Kmax, + VertexAttribute& Kmin, + const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + FunctorComputeCurvatureVertices_QuadraticFitting funct(map, position, normal, kmax, kmin, Kmax, Kmin); + Algo::Parallel::foreach_cell(map, funct, nbth, true, select, current_thread); +} + +} // namespace Parallel + + } // namespace Geometry } // namespace Algo diff --git a/include/Algo/Geometry/inclusion.hpp b/include/Algo/Geometry/inclusion.hpp index f77ef3e79fe9f4d97152b034a88812f5c1068cec..5631c656b85e4ff0b0e570e6544dce97525ebc3d 100644 --- a/include/Algo/Geometry/inclusion.hpp +++ b/include/Algo/Geometry/inclusion.hpp @@ -62,6 +62,7 @@ bool isConvex(typename PFP::MAP& map, Dart d, const VertexAttribute bool isPointInVolume(typename PFP::MAP& map, Dart d, const VertexAttribute& position, const typename PFP::VEC3& point) { @@ -69,59 +70,58 @@ bool isPointInVolume(typename PFP::MAP& map, Dart d, const VertexAttribute(map,d)) { -// CGoGNout << "optimize point in volume" << CGoGNendl; -// } - - std::list visitedFaces; // Faces that are traversed - visitedFaces.push_back(d); // Start with the face of d - std::list::iterator face; - VEC3 dir(0.5f,0.5f,0.5f); - VEC3 inter; + VEC3 dir(0.9f,1.1f,1.3f); std::vector interPrec; - - DartMarkerStore mark(map); // Lock a marker - // For every face added to the list - // search the number of faces intersected by a ray whose origin is the tested point - for (face = visitedFaces.begin(); face != visitedFaces.end(); ++face) + interPrec.reserve(16); + std::vector visitedFaces; // Faces that are traversed + visitedFaces.reserve(64); + visitedFaces.push_back(d); // Start with the face of d + DartMarkerStore mark(map); + mark.markOrbit(d) ; + for(unsigned int iface = 0; iface != visitedFaces.size(); ++iface) { - if (!mark.isMarked(*face)) // Face has not been visited yet + Dart e = visitedFaces[iface]; + VEC3 inter; + bool interRes = Algo::Geometry::intersectionLineConvexFace(map, e, position, point, dir, inter); + if (interRes) { + // check if already intersect on same point (a vertex certainly) bool alreadyfound = false; - bool interRes = Algo::Geometry::intersectionLineConvexFace(map, *face, position, point, dir, inter); - if(interRes && (dir * (inter-point)) >= 0.0f) + for(typename std::vector::iterator it = interPrec.begin(); !alreadyfound && it != interPrec.end(); ++it) { - if(interPrec.size() > 0) - { - for(typename std::vector::iterator it = interPrec.begin(); !alreadyfound && it != interPrec.end(); ++it) - { - if((*it)[0] == inter[0]) - alreadyfound = true; - } - } - if(!alreadyfound) - { + if (Geom::arePointsEquals(*it,inter)) + alreadyfound = true; + } + + if (!alreadyfound) + { + float v = dir * (inter-point); + if (v>0) ++countInter; - interPrec.push_back(inter); - } - - // add non visited adjacent faces to the list of face - Dart dNext = *face ; - do - { - mark.mark(dNext); // Mark - Dart adj = map.phi2(dNext); // Get adjacent face - if (adj != dNext && !mark.isMarked(adj)) - visitedFaces.push_back(adj); // Add it - dNext = map.phi1(dNext) ; - } while(dNext != *face) ; + if (v<0) + ++countInter2; + interPrec.push_back(inter); } } + // add all face neighbours to the table + Dart currentFace = e; + do + { + Dart ee = map.phi2(e) ; + if(!mark.isMarked(ee)) // not already marked + { + visitedFaces.push_back(ee) ; + mark.markOrbit(ee) ; + } + e = map.phi1(e) ; + } while(e != currentFace) ; } //if the point is in the volume there is an odd number of intersection with all faces with any direction - return (countInter % 2) == 1; + return ((countInter % 2) != 0) && ((countInter2 % 2) != 0); // return (countInter % 2) == 1; + } template diff --git a/include/Algo/Geometry/normal.h b/include/Algo/Geometry/normal.h index fe168b9ddcf74d82c6e2d259180a313077bf420a..b466d9877339f1af80b4b9e846482a3dec6d0af8 100644 --- a/include/Algo/Geometry/normal.h +++ b/include/Algo/Geometry/normal.h @@ -27,6 +27,7 @@ #include "Geometry/basic.h" + namespace CGoGN { @@ -54,6 +55,7 @@ typename PFP::VEC3 vertexBorderNormal(typename PFP::MAP& map, Dart d, const Vert template void computeNormalFaces(typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& face_normal, const FunctorSelect& select = allDarts, unsigned int thread = 0) ; + /** * compute normals of vertices * @param map the map on which we work @@ -65,12 +67,26 @@ void computeNormalFaces(typename PFP::MAP& map, const VertexAttribute void computeNormalVertices(typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& normal, const FunctorSelect& select = allDarts, unsigned int thread = 0) ; + +namespace Parallel +{ +template +void computeNormalVertices(typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& normal, const FunctorSelect& select = allDarts, unsigned int nbth = 0, unsigned int current_thread = 0) ; + + +template +void computeNormalFaces(typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& face_normal, const FunctorSelect& select = allDarts, unsigned int nbth = 0, unsigned int thread = 0) ; + +} + + template typename PFP::REAL computeAngleBetweenNormalsOnEdge(typename PFP::MAP& map, Dart d, VertexAttribute& position) ; template void computeAnglesBetweenNormalsOnEdges(typename PFP::MAP& map, const VertexAttribute& position, EdgeAttribute& angles, const FunctorSelect& select = allDarts, unsigned int thread = 0) ; + } // namespace Geometry } // namespace Algo diff --git a/include/Algo/Geometry/normal.hpp b/include/Algo/Geometry/normal.hpp index 04f71ded565f12232f1010c51bccda4e0d1d0aac..38ef2f7d9bb1eb75f6677c68e5beae79f1f2f9c9 100644 --- a/include/Algo/Geometry/normal.hpp +++ b/include/Algo/Geometry/normal.hpp @@ -28,6 +28,8 @@ #include "Topology/generic/traversorCell.h" #include "Topology/generic/traversor2.h" +#include "Algo/Parallel/parallel_foreach.h" + #include namespace CGoGN @@ -163,6 +165,87 @@ void computeNormalVertices(typename PFP::MAP& map, const VertexAttribute(map, d, position) ; } + + +namespace Parallel +{ + +template +class FunctorComputeNormalVertices: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + VertexAttribute& m_normal; +public: + FunctorComputeNormalVertices( typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& normal): + FunctorMapThreaded(map), m_position(position), m_normal(normal) + { } + + void run(Dart d, unsigned int threadID) + { + m_normal[d] = vertexNormal(this->m_map, d, m_position) ; + } +}; + +template +void computeNormalVertices(typename PFP::MAP& map, const VertexAttribute& position, VertexAttribute& normal, const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + FunctorComputeNormalVertices funct(map,position,normal); + Algo::Parallel::foreach_cell(map, funct, nbth, false, select, current_thread); +} + + +template +class FunctorComputeNormalFaces: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + FaceAttribute& m_normal; +public: + FunctorComputeNormalFaces( typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& normal): + FunctorMapThreaded(map), m_position(position), m_normal(normal) + { } + + void run(Dart d, unsigned int threadID) + { + m_normal[d] = faceNormal(this->m_map, d, m_position) ; + } +}; + +template +void computeNormalFaces(typename PFP::MAP& map, const VertexAttribute& position, FaceAttribute& normal, const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + FunctorComputeNormalFaces funct(map,position,normal); + Algo::Parallel::foreach_cell(map, funct, nbth, false, select, current_thread); +} + + +template +class FunctorComputeAngleBetweenNormalsOnEdge: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + FaceAttribute& m_angles; +public: + FunctorComputeAngleBetweenNormalsOnEdge( typename PFP::MAP& map, const VertexAttribute& position, EdgeAttribute& angles): + FunctorMapThreaded(map), m_position(position), m_angles(angles) + { } + + void run(Dart d, unsigned int threadID) + { + m_angles[d] = computeAngleBetweenNormalsOnEdge(this->m_map, d, m_position) ; + } +}; + + +template +void computeAnglesBetweenNormalsOnEdges(typename PFP::MAP& map, const VertexAttribute& position, EdgeAttribute& angles, const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + FunctorComputeAngleBetweenNormalsOnEdge funct(map,position,angles); + Algo::Parallel::foreach_cell(map, funct, nbth, false, select, current_thread); +} + +} // endnamespace Parallel + + + template typename PFP::REAL computeAngleBetweenNormalsOnEdge(typename PFP::MAP& map, Dart d, const VertexAttribute& position) { diff --git a/include/Algo/Geometry/volume.h b/include/Algo/Geometry/volume.h index ba492ca6df7a656ebc9b65ca759d91b4f596b6c4..c00f67653fcf86964c2fbeb2f800156c4bb22117 100644 --- a/include/Algo/Geometry/volume.h +++ b/include/Algo/Geometry/volume.h @@ -43,10 +43,18 @@ template typename PFP::REAL tetrahedronVolume(typename PFP::MAP& map, Dart d, const VertexAttribute& position) ; template -typename PFP::REAL convexPolyhedronVolume(typename PFP::MAP& map, Dart d, const VertexAttribute& position) ; +typename PFP::REAL convexPolyhedronVolume(typename PFP::MAP& map, Dart d, const VertexAttribute& position, unsigned int thread=0) ; template -typename PFP::REAL totalVolume(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& select = allDarts) ; +typename PFP::REAL totalVolume(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& select = allDarts, unsigned int thread = 0) ; + + +namespace Parallel +{ +template +typename PFP::REAL totalVolume(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& select = allDarts, unsigned int nbth = 0, unsigned int current_thread = 0) ; + +} } // namespace Geometry diff --git a/include/Algo/Geometry/volume.hpp b/include/Algo/Geometry/volume.hpp index 2f29eb5001409b7f7b9163023ebb5e5918bc9e37..cfaec6b054129465cf94fa8aa1dc8aaba529d30e 100644 --- a/include/Algo/Geometry/volume.hpp +++ b/include/Algo/Geometry/volume.hpp @@ -58,27 +58,28 @@ typename PFP::REAL tetrahedronVolume(typename PFP::MAP& map, Dart d, const Verte } template -typename PFP::REAL convexPolyhedronVolume(typename PFP::MAP& map, Dart d, const VertexAttribute& position) +typename PFP::REAL convexPolyhedronVolume(typename PFP::MAP& map, Dart d, const VertexAttribute& position, unsigned int thread) { typedef typename PFP::VEC3 VEC3; - if(Modelisation::Tetrahedralization::isTetrahedron(map,d)) + if(Modelisation::Tetrahedralization::isTetrahedron(map,d,thread)) return tetrahedronVolume(map,d,position) ; else { typename PFP::REAL vol = 0 ; - VEC3 vCentroid = Algo::Geometry::volumeCentroid(map, d, position) ; + VEC3 vCentroid = Algo::Geometry::volumeCentroid(map, d, position, thread) ; - DartMarkerStore mark(map); // Lock a marker + DartMarkerStore mark(map,thread); // Lock a marker std::vector visitedFaces ; visitedFaces.reserve(100) ; + visitedFaces.push_back(d) ; mark.markOrbit(d) ; - for(typename std::vector::iterator face = visitedFaces.begin(); face != visitedFaces.end(); ++face) + for(unsigned int iface = 0; iface != visitedFaces.size(); ++iface) { - Dart e = *face ; + Dart e = visitedFaces[iface] ; if(map.isCycleTriangle(e)) { VEC3 p1 = position[e] ; @@ -98,30 +99,87 @@ typename PFP::REAL convexPolyhedronVolume(typename PFP::MAP& map, Dart d, const f = map.phi1(f) ; } while(f != e) ; } + Dart currentFace = e; do // add all face neighbours to the table { Dart ee = map.phi2(e) ; if(!mark.isMarked(ee)) // not already marked { visitedFaces.push_back(ee) ; - mark.markOrbit(e) ; + mark.markOrbit(ee) ; } e = map.phi1(e) ; - } while(e != *face) ; + } while(e != currentFace) ; } return vol ; } } + template -float totalVolume(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& select) +typename PFP::REAL totalVolume(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& select, unsigned int thread) { - typename PFP::REAL vol = 0 ; - TraversorW t(map, select) ; + double vol = 0.0 ; + + TraversorW t(map, select, thread) ; for(Dart d = t.begin(); d != t.end(); d = t.next()) - vol += convexPolyhedronVolume(map, d, position) ; - return vol ; + vol += convexPolyhedronVolume(map, d, position,thread) ; + return typename PFP::REAL(vol) ; +} + + +namespace Parallel +{ + +template +class FunctorTotalVolume: public FunctorMapThreaded +{ + const VertexAttribute& m_position; + double m_vol; +public: + FunctorTotalVolume( typename PFP::MAP& map, const VertexAttribute& position): + FunctorMapThreaded(map), m_position(position), m_vol(0.0) + { } + + void run(Dart d, unsigned int threadID) + { + m_vol += convexPolyhedronVolume(this->m_map, d, m_position,threadID) ; + } + + double getVol() const + { + return m_vol; + } +}; + + + +template +typename PFP::REAL totalVolume(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& select, unsigned int nbth, unsigned int current_thread) +{ + if (nbth==0) + nbth = Algo::Parallel::optimalNbThreads(); + + + std::vector*> functs; + for (unsigned int i=0; i < nbth; ++i) + { + functs.push_back(new FunctorTotalVolume(map,position)); + } + + double total=0.0; + + Algo::Parallel::foreach_cell(map, functs, true, select, current_thread); + + for (unsigned int i=0; i < nbth; ++i) + { + total += reinterpret_cast*>(functs[i])->getVol(); + delete functs[i]; + } + return typename PFP::REAL(total); +} + } } // namespace Geometry diff --git a/include/Algo/ImplicitHierarchicalMesh/ihm3.h b/include/Algo/ImplicitHierarchicalMesh/ihm3.h index d1754614e4860e07f78450604e9c82e0bf9bd470..dc411713c00b31aa1c90faf9ab7b00f81dddb23a 100644 --- a/include/Algo/ImplicitHierarchicalMesh/ihm3.h +++ b/include/Algo/ImplicitHierarchicalMesh/ihm3.h @@ -78,6 +78,12 @@ public: */ void init() ; + /** + * clear the map + * @param remove attrib remove attribute (not only clear the content) + */ + void clear(bool removeAttrib); + /*! @name Attributes Management * To handles Attributes for each level of an implicit 3-map *************************************************************************/ diff --git a/include/Algo/Modelisation/tetrahedralization.h b/include/Algo/Modelisation/tetrahedralization.h index 11ac8f5b21ae45d0362834a28611c81120c02643..35a209240572a16e97e06597f55df979db7d9fc8 100644 --- a/include/Algo/Modelisation/tetrahedralization.h +++ b/include/Algo/Modelisation/tetrahedralization.h @@ -70,7 +70,7 @@ Dart splitVertex(typename PFP::MAP& map, std::vector& vd); * @param a dart from the volume */ template -bool isTetrahedron(typename PFP::MAP& the_map, Dart d); +bool isTetrahedron(typename PFP::MAP& the_map, Dart d, unsigned int thread=0); /** * test if a mesh (or submesh) is a tetrahedral mesh diff --git a/include/Algo/Modelisation/tetrahedralization.hpp b/include/Algo/Modelisation/tetrahedralization.hpp index eacd899127fd6591189b484bb5363e8c32c97f5f..ea2ef5cf33f6b5a2eed4d5e8d3865c18cd63dec5 100644 --- a/include/Algo/Modelisation/tetrahedralization.hpp +++ b/include/Algo/Modelisation/tetrahedralization.hpp @@ -216,12 +216,12 @@ Dart splitVertex(typename PFP::MAP& map, std::vector& vd) ************************************************************************************************/ template -bool isTetrahedron(typename PFP::MAP& the_map, Dart d) +bool isTetrahedron(typename PFP::MAP& the_map, Dart d, unsigned int thread) { unsigned int nbFaces = 0; //Test the number of faces end its valency - Traversor3WF travWF(the_map, d); + Traversor3WF travWF(the_map, d, false, thread); for(Dart dit = travWF.begin() ; dit != travWF.end(); dit = travWF.next()) { //increase the number of faces diff --git a/include/Algo/Parallel/cgogn_thread.h b/include/Algo/Parallel/cgogn_thread.h new file mode 100644 index 0000000000000000000000000000000000000000..d01494883b4d2422e926c5eb09f70bc29a36b17d --- /dev/null +++ b/include/Algo/Parallel/cgogn_thread.h @@ -0,0 +1,78 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, 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. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ +#ifndef __PARALLEL_THREAD__ +#define __PARALLEL_THREAD__ + +namespace CGoGN +{ + +namespace Algo +{ + +namespace Parallel +{ + +/** + * Class to encapsulate algorithm in a boost thread + * Usage: + * - Define a class MyCGoGNThread that inherit from CGoGNThread + * - call with boost::thread cgt1(MyCGoGNThread(map,1, ...); + * - wait to finish: cgt1.join(); + * + * TODO: write a CGoGNThread version of "all" algorithm + */ +template +class CGoGNThread +{ +protected: + MAP& m_map; + unsigned int m_threadId; + + unsigned int tid() + { + return m_threadId; + } + +public: + CGoGNThread(MAP& map, unsigned int th): + m_map(map), m_threadId(th) {} + + virtual ~CGoGNThread() {} + + /** + * to implement with algo to execute (use m_threadId) + */ + virtual void operator()()=0; + + +}; + + +} // namespace Parallel + +} // namespace Algo + +} // namespace CGoGN + +#endif diff --git a/include/Algo/Parallel/parallel_foreach.h b/include/Algo/Parallel/parallel_foreach.h index fe0f0885fd422e93ecbead46c061e5afff1a8433..0feeffc7d63e1079c5631b4ec75f3ddccaab103f 100644 --- a/include/Algo/Parallel/parallel_foreach.h +++ b/include/Algo/Parallel/parallel_foreach.h @@ -22,11 +22,12 @@ * * *******************************************************************************/ -#include "Topology/generic/functor.h" #ifndef __PARALLEL_FOREACH__ #define __PARALLEL_FOREACH__ +#include "Topology/generic/functor.h" + namespace CGoGN { @@ -36,186 +37,169 @@ namespace Algo namespace Parallel { -// TODO a deplacer dans functor.h -/** - * Functor class for parallel::foreach_xxx - */ -template -class FunctorMapThreaded: public FunctorMap -{ -protected: - // current thread id - unsigned int m_threadId; -public: - /** - * constructor - * @param map traversed map - * @param th current thread id - */ - FunctorMapThreaded(MAP& m, unsigned int th = 0): FunctorMap(m), m_threadId(th) {} - - /** - * Method that duplicate the fonctor for each thread, typically: - * FunctorXXXX* copy = new FunctorXXXX(this->m_map,pos,norm,id); - * return reinterpret_cast*>(copy); - * @param id thread id assigned to functor - */ - virtual FunctorMapThreaded* duplicate(unsigned int id)=0; -}; +static unsigned int NBCORES=0; -/** - * Functor class for parallel::foreach_xxx_res - */ -template -class FunctorMapThreadedResult: public FunctorMapThreaded -{ -public: - FunctorMapThreadedResult(MAP& m, unsigned int th = 0): FunctorMapThreaded(m,th) {} +/// enum for optimalNbThreads parameter +enum NbParam {NB_HIGHMEMORY, NB_HIGHCOMPUTE, NB_VERYHIGHMEMORY}; - /** - * get back result (used by foreach_xxx_res for filling vector of results - */ - virtual T getResult() = 0; -}; +/// size of buffers to store darts or indexes in each threads +const unsigned int SIZE_BUFFER_THREAD = 8192; // seems to be the best compromise /** - * Traverse orbits of a map in parallel. Use topological marker - * Functor application must be independant - * @param map the map - * @param func the functor to apply - * @param nbth number of thread to use - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) - * @param good a selector + * @return How much threads has you computer */ -template -void foreach_orbit(typename PFP::MAP& map, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff = 8192, bool needMarkers = false, const FunctorSelect& good = allDarts); +inline unsigned int nbThreads(); /** - * Traverse cells of a map in parallel. Use embedding marker - * Functor application must be independant - * @param map the map - * @param orbit the cell (VERTEX/EDGE/FACE/.. - * @param func the functor to apply - * @param nbth number of threads - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) - * @param good a selector + * @param p can be NB_HIGHMEMORY (default) or NB_HIGHCOMPUTE or NB_VERYHIGHMEMORY + * @return Number of core in fact (work only with quad core with/without hyper threading) */ -template -void foreach_cell(typename PFP::MAP& map, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff = 8192, bool needMarkers = false, const FunctorSelect& good = allDarts); +unsigned int optimalNbThreads( NbParam p=NB_HIGHMEMORY); +/** + * impossible to automatically determine the number of cores so ... + */ +void setNbCore(unsigned int nb); + + +// +//template +//class Foreach +//{ +// MAP& m_map; +// +// std::vector*> m_funcs; +// +// std::vector* m_vd; +// +// unsigned int m_nbth; +// +//public: +// Foreach(MAP& map,unsigned int nbth); +// +// void clearFunctors(); +// +// void addFunctor(FunctorMapThreaded* funcPtr); +// +// template +// T* getFunctor(unsigned int i); +// +// template +// void traverseCell(bool needMarkers = false, const FunctorSelect& good = allDarts, unsigned int currentThread = 0); +// +// template +// void traverseEachCell(bool needMarkers = false, const FunctorSelect& good = allDarts, unsigned int currentThread = 0); +// +// void traverseDart(bool needMarkers = false, const FunctorSelect& good = allDarts, unsigned int currentThread = 0); +// +// void traverseEachDart(bool needMarkers = false, const FunctorSelect& good = allDarts, unsigned int currentThread = 0); +//}; -template -void foreach_cell2Pass(typename PFP::MAP& map, FunctorMapThreaded& funcFront, FunctorMapThreaded& funcBack, unsigned int nbLoops, unsigned int nbth, unsigned int szbuff = 8192, bool needMarkers = false, const FunctorSelect& good = allDarts); /** - * Traverse darts of a map in parallel - * Functor application must be independant + * Traverse cells of a map in parallel. Use quick traversal, cell markers or dart markers if available ! + * Use this version if you need to have acces to each functors after the traversal (to compute a sum or an average for example) * @param map the map - * @param func the functor to apply - * @param nbth number of thread to use - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) + * @param funcs the functors to apply (size of vector determine number of threads, and all functors must be of the same type) + * @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !! * @param good a selector */ -template -void foreach_dart(typename PFP::MAP& map, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff = 8192, bool needMarkers = false, const FunctorSelect& good = allDarts); +template +void foreach_cell(MAP& map, std::vector*>& funcs, bool needMarkers = false, const FunctorSelect& good = allDarts, unsigned int currentThread = 0); /** - * Traverse orbits of a map in parallel. Use topo marker - * Use this version if you want to store a result for traversal (sum, average, max, etc..) + * Traverse cells of a map in parallel. Use quick traversal, cell markers or dart markers if available ! + * Use this version if you do not need to keep functors * @param map the map - * @param orbit the cell (VERTEX/EDGE/FACE/.. * @param func the functor to apply - * @param nbth number of threads - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param results output of the FunctorMapThreadedResult of each thread - * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) + * @param nbth number of threads 0 for let the system choose + * @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !! * @param good a selector */ -template -void foreach_orbit_res(typename PFP::MAP& map, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers = false, const FunctorSelect& good = allDarts); +template +void foreach_cell(MAP& map, FunctorMapThreaded& func, unsigned int nbth = 0, bool needMarkers = false, const FunctorSelect& good = allDarts, unsigned int currentThread = 0); + /** - * Traverse cells of a map in parallel. Use embedding marker - * Use this version if you want to store a result for traversal (sum, average, max, etc..) + * Traverse cells of a map and apply differents functors in // + * Use this version if you need to have acces to each functors after the traversal (to compute a sum or an average for example) * @param map the map - * @param orbit the cell (VERTEX/EDGE/FACE/.. - * @param func the functor to apply + * @param funcs the functors to apply ( each functors can (should!) be here of different type) * @param nbth number of threads - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param results output of the FunctorMapThreadedResult of each thread - * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) + * @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !! * @param good a selector */ -template -void foreach_cell_res(typename PFP::MAP& map, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers = false, const FunctorSelect& good = allDarts); +template +void foreach_cell_all_thread(MAP& map, std::vector*>& funcs, bool needMarkers = false, const FunctorSelect& good = allDarts, unsigned int currentThread = 0); + /** - * Traverse cells of a map in parallel. Use embedding marker - * Use this version if you want to store a result for traversal (sum, average, max, etc..) + * Traverse darts of a map in parallel + * Use this version if you need to have acces to each functors after the traversal (to compute a sum or an average for example) * @param map the map - * @param orbit the cell (VERTEX/EDGE/FACE/.. - * @param func the functor to apply - * @param nbth number of threads - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param results output of the FunctorMapThreadedResult of each thread - * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) + * @param funcs the functors to apply (size of vector determine number of threads, and all functors must be of the same type) + * @param needMarkers set to yes if you want that each thread use different markers.Warning if set to false (default) do not use algo with thread id or markers !! * @param good a selector */ -template -void foreach_dart_res(typename PFP::MAP& map, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers = false, const FunctorSelect& good = allDarts); +template +void foreach_dart(MAP& map, std::vector*>& funcs, unsigned int nbth, bool needMarkers = false, const FunctorSelect& good = allDarts); + /** - * easy sum of returned result of foreach_xxx_res + * Traverse darts of a map in parallel + * @param map the map + * @param funcs the functor + * @param nbth number of thread to use, 0 for let the system choose + * @param needMarkers set to yes if you want that each thread use different markers. Warning if set to false (default) do not use algo with thread id or markers !! + * @param good a selector */ -template -T sumResult(const std::vector& res); +template +void foreach_dart(MAP& map, FunctorMapThreaded& func, unsigned int nbth = 0, bool needMarkers = false, const FunctorSelect& good = allDarts); + /** - * easy sum of returned result of foreach_xxx_res + * Traverse all elements of an attribute container (attribute handler is placed in FunctorAttribThreaded) + * @param attr_cont the attribute container to traverse + * @param func the fonctors to use */ -template -std::pair sumPairResult(const std::vector< std::pair >& res); +void foreach_attrib(AttributeContainer& attr_cont, std::vector funcs); /** - * easy max of returned result of foreach_xxx_res + * Traverse all elements of an attribute container (attribute handler is placed in FunctorAttribThreaded + * @param attr_cont the attribute container to traverse + * @param func the functor to use + * @param nbth number of thread to use for computation 0 for let the system choose */ -template -T maxResult(const std::vector& res); +void foreach_attrib(AttributeContainer& attr_cont, FunctorAttribThreaded& func, unsigned int nbth = 0); + /** - * easy min of returned result of foreach_xxx_res + * Optimized version for // foreach with to pass (2 functors), with several loops + * Use this version if you need to keep functors + * @param map the map + * @param funcsFrontnBack nbth front pass functors followed by nbth back pass functors + * @param nbLoops number of loops to execute + * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) + * @param good a selector */ -template -T minResult(const std::vector& res); - +template +void foreach_cell2Pass(MAP& map, std::vector*>& funcsFrontnBack, unsigned int nbLoops, bool needMarkers = false, const FunctorSelect& good = allDarts); /** - * Class to encapsulate algorithm in a boost thread - * Usage: - * - Define a class MyCGoGNThread that inherit from CGoGNThread - * - call with boost::thread cgt1(MyCGoGNThread(map,1, ...); - * - wait to finish: cgt1.join(); + * Optimized version for // foreach with to pass (2 functors), with several loops + * Use this version if you do not need to keep functors + * @param map the map + * @param funcFront front pass functor + * @param funcBack back pass functor + * @param nbLoops number of loops to execute + * @param nbth number of threads to use + * @param needMarkers set to yes if you want that each thread use different markers (markers are allocated if necessary) + * @param good a selector */ -template -class CGoGNThread -{ -protected: - MAP& m_map; - unsigned int m_threadId; - -public: - CGoGNThread(MAP& map, unsigned int th): - m_map(map), m_threadId(th) {} - - /** - * to implement with algo to execute (use m_threadId - */ - virtual void operator()() =0; -}; +template +void foreach_cell2Pass(MAP& map, FunctorMapThreaded& funcFront, FunctorMapThreaded& funcBack, unsigned int nbLoops, unsigned int nbth, bool needMarkers = false, const FunctorSelect& good = allDarts); + } // namespace Parallel diff --git a/include/Algo/Parallel/parallel_foreach.hpp b/include/Algo/Parallel/parallel_foreach.hpp index 90e6ed65f71d61cab3c95751ff9b4fad399c9b84..0dc91e0af6e8bcb8b73034f7c6539d2c778e3a79 100644 --- a/include/Algo/Parallel/parallel_foreach.hpp +++ b/include/Algo/Parallel/parallel_foreach.hpp @@ -25,6 +25,7 @@ #include #include + namespace CGoGN { @@ -34,230 +35,201 @@ namespace Algo namespace Parallel { - -/** - * - */ -template -class ThreadFunction +/// internal functor for boost call +class ThreadFunctionAttrib { protected: - std::vector& m_darts; + std::vector& m_ids; boost::barrier& m_sync1; boost::barrier& m_sync2; bool& m_finished; - FunctorMapThreaded* m_functor; + unsigned int m_id; + FunctorAttribThreaded* m_functor; + public: - ThreadFunction(FunctorMapThreaded& func, std::vector& vd, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id): - m_darts(vd), m_sync1(s1), m_sync2(s2), m_finished(finished) + ThreadFunctionAttrib(FunctorAttribThreaded* func, std::vector& vid, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id): + m_ids(vid), m_sync1(s1), m_sync2(s2), m_finished(finished), m_id(id), m_functor(func) { - m_functor = func.duplicate(id); } - ThreadFunction(const ThreadFunction& tf): - m_darts(tf.m_darts), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_functor(tf.m_functor){} + ThreadFunctionAttrib(const ThreadFunctionAttrib& tf): + m_ids(tf.m_ids), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_id(tf.m_id), m_functor(tf.m_functor){} void operator()() { while (!m_finished) { - for (std::vector::const_iterator it = m_darts.begin(); it != m_darts.end(); ++it) - m_functor->operator()(*it); + for (std::vector::const_iterator it = m_ids.begin(); it != m_ids.end(); ++it) + m_functor->run(*it,m_id); m_sync1.wait(); m_sync2.wait(); } } - - void clean() - { - delete m_functor; - } - }; -template -class ThreadFunctionResult + +/// internal functor for boost call +template +class ThreadFunction { protected: std::vector& m_darts; boost::barrier& m_sync1; boost::barrier& m_sync2; bool& m_finished; - FunctorMapThreadedResult* m_functor; - T& m_result; + unsigned int m_id; + FunctorMapThreaded* m_functor; public: - ThreadFunctionResult(FunctorMapThreadedResult& func, std::vector& vd, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id, T& result): - m_darts(vd), m_sync1(s1), m_sync2(s2), m_finished(finished), m_result(result) + ThreadFunction(FunctorMapThreaded* func, std::vector& vd, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id): + m_darts(vd), m_sync1(s1), m_sync2(s2), m_finished(finished), m_id(id), m_functor(func) { - m_functor = reinterpret_cast< FunctorMapThreadedResult* >(func.duplicate(id)); } - ThreadFunctionResult(const ThreadFunctionResult& tf): - m_darts(tf.m_darts), - m_sync1(tf.m_sync1), - m_sync2(tf.m_sync2), - m_finished(tf.m_finished), - m_functor(tf.m_functor), - m_result(tf.m_result){} + ThreadFunction(const ThreadFunction& tf): + m_darts(tf.m_darts), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_id(tf.m_id), m_functor(tf.m_functor){} void operator()() { - while (!m_finished) { for (std::vector::const_iterator it = m_darts.begin(); it != m_darts.end(); ++it) - m_functor->operator()(*it); + m_functor->run(*it,m_id); m_sync1.wait(); m_sync2.wait(); } - m_result = this->m_functor->getResult(); - } - - void clean() - { - delete m_functor; } }; +inline unsigned int nbThreads() +{ + return boost::thread::hardware_concurrency(); +} + -template -void foreach_orbit(typename PFP::MAP& map, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff, bool needMarkers, const FunctorSelect& good) +inline unsigned int optimalNbThreads(NbParam p) { - std::vector* vd = new std::vector[nbth]; - boost::thread** threads = new boost::thread*[nbth]; + if (p==NB_HIGHCOMPUTE) + return nbThreads(); + if (p==NB_VERYHIGHMEMORY) + return 2; + + // NB_HIGHMEMORY + if (NBCORES != 0) + return NBCORES; + unsigned int nb = nbThreads(); + if (nb>4) + return nb/2 ; + return nb; - DartMarker dm(map); - Dart d = map.begin(); +} - // nbth new functions, new thread (with good darts !) - for (unsigned int i=0; i(d); - vd[nb%nbth].push_back(d); - nb++; - } - map.next(d); - } - if (needMarkers) - { - // ensure that there is enough threads - unsigned int nbth_prec = map.getNbThreadMarkers(); - if (nbth_prec < nbth+1) - map.addThreadMarker(nbth+1-nbth_prec); - } +template +void foreach_cell(MAP& map, FunctorMapThreaded& func, unsigned int nbth, bool needMarkers, const FunctorSelect& good, unsigned int currentThread) +{ + if (nbth == 0) + nbth = optimalNbThreads(); - boost::barrier sync1(nbth+1); - boost::barrier sync2(nbth+1); - bool finished = false; - // lauch threads - if (needMarkers) + std::vector*> funcs; + funcs.reserve(nbth); + + FunctorMapThreaded* ptr = func.duplicate(); + bool shared = (ptr == NULL); + + if (shared) { for (unsigned int i = 0; i < nbth; ++i) - threads[i] = new boost::thread(ThreadFunction(func, vd[i],sync1,sync2, finished,1+i)); + funcs.push_back(&func); } else { - for (unsigned int i = 0; i < nbth; ++i) - threads[i] = new boost::thread(ThreadFunction(func, vd[i],sync1,sync2, finished,0)); + funcs.push_back(ptr); + for (unsigned int i = 1; i < nbth; ++i) + funcs.push_back(func.duplicate()); } - // and continue to traverse the map - std::vector* tempo = new std::vector[nbth]; - - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].reserve(szbuff); - - while (d != map.end()) - { - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].clear(); - - unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) - { - if (good(d) && (!dm.isMarked(d))) - { - dm.markOrbit(d); - tempo[nb%nbth].push_back(d); - nb++; - } - map.next(d); - } + foreach_cell(map,funcs,needMarkers,good,currentThread); - // sync and swap the two vectors - sync1.wait(); + if (!shared) for (unsigned int i = 0; i < nbth; ++i) - vd[i].swap(tempo[i]); - sync2.wait(); - } - - sync1.wait(); - finished = true; - sync2.wait(); - - //wait for all theads to be finished - for (unsigned int i = 0; i < nbth; ++i) - { - threads[i]->join(); - delete threads[i]; - } - - // and release memory - delete[] threads; - delete[] vd; - delete[] tempo; + delete funcs[i]; } -/** - * Traverse cells of a map in parallel. Use embedding marker - * Functor application must be independant - * @param map the map - * @param func the functor to apply - * @param nbth number of thread to use (use twice as threads of processor) - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param good a selector - */ -template -void foreach_cell(typename PFP::MAP& map, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff, bool needMarkers, const FunctorSelect& good) +template +void foreach_cell(MAP& map, std::vector*>& funcs, bool needMarkers, const FunctorSelect& good, unsigned int currentThread) { + unsigned int nbth = funcs.size(); + std::vector* vd = new std::vector[nbth]; boost::thread** threads = new boost::thread*[nbth]; - CellMarker cm(map); - Dart d = map.begin(); - // nbth new functions, new thread (with good darts !) for (unsigned int i = 0; i < nbth; ++i) - vd[i].reserve(szbuff); + vd[i].reserve(SIZE_BUFFER_THREAD); - // fill each vd buffers with 4096 darts - unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + AttributeContainer* cont = NULL; + DartMarker* dmark = NULL; + CellMarker* cmark = NULL; + AttributeMultiVector* quickTraversal = map.template getQuickTraversal() ; + + // fill each vd buffers with SIZE_BUFFER_THREAD darts + Dart d; + unsigned int di=0; + + if(quickTraversal != NULL) { - if (good(d) && (!cm.isMarked(d))) + cont = &(map.template getAttributeContainer()) ; + + di = cont->begin(); + unsigned int nb = 0; + while ((di != cont->end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { - cm.mark(d); - vd[nb%nbth].push_back(d); - nb++; + d = quickTraversal->operator[](di); + if (good(d)) + { + vd[nb%nbth].push_back(d); + nb++; + } + cont->next(di); } - map.next(d); } - - if (needMarkers) + else { - // ensure that there is enough threads - unsigned int nbth_prec = map.getNbThreadMarkers(); - if (nbth_prec < nbth+1) - map.addThreadMarker(nbth+1-nbth_prec); + if(map.template isOrbitEmbedded()) + { + cmark = new CellMarker(map, currentThread) ; + + d = map.begin(); + unsigned int nb = 0; + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!cmark->isMarked(d))) + { + cmark->mark(d); + vd[nb%nbth].push_back(d); + nb++; + } + map.next(d); + } + } + else + { + dmark = new DartMarker(map, currentThread) ; + d = map.begin(); + unsigned int nb = 0; + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!dmark->isMarked(d))) + { + dmark->markOrbit(d); + vd[nb%nbth].push_back(d); + nb++; + } + map.next(d); + } + } } boost::barrier sync1(nbth+1); @@ -266,41 +238,89 @@ void foreach_cell(typename PFP::MAP& map, FunctorMapThreaded& // lauch threads if (needMarkers) { - for (unsigned int i = 0; i < nbth; ++i) - threads[i] = new boost::thread(ThreadFunction(func, vd[i],sync1,sync2, finished,1+i)); - } - else - { - for (unsigned int i = 0; i < nbth; ++i) - threads[i] = new boost::thread(ThreadFunction(func, vd[i],sync1,sync2, finished,0)); + unsigned int nbth_prec = map.getNbThreadMarkers(); + if (nbth_prec < nbth+1) + map.addThreadMarker(nbth+1-nbth_prec); } + + for (unsigned int i = 0; i < nbth; ++i) + threads[i] = new boost::thread(ThreadFunction(funcs[i], vd[i],sync1,sync2, finished,1+i)); + // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i = 0; i < nbth; ++i) - tempo[i].reserve(szbuff); + tempo[i].reserve(SIZE_BUFFER_THREAD); - while (d != map.end()) - { - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].clear(); - unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + if (cont) + { + while (di != cont->end()) { - if (good(d) && (!cm.isMarked(d))) + for (unsigned int i = 0; i < nbth; ++i) + tempo[i].clear(); + unsigned int nb = 0; + while ((di != cont->end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { - cm.mark(d); - tempo[nb%nbth].push_back(d); - nb++; + d = quickTraversal->operator[](di); + if (good(d)) + { + tempo[nb%nbth].push_back(d); + nb++; + } + cont->next(di); } - map.next(d); + sync1.wait(); + for (unsigned int i = 0; i < nbth; ++i) + vd[i].swap(tempo[i]); + sync2.wait(); + } + } + else if (cmark) + { + while (d != map.end()) + { + for (unsigned int i = 0; i < nbth; ++i) + tempo[i].clear(); + unsigned int nb = 0; + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!cmark->isMarked(d))) + { + cmark->mark(d); + tempo[nb%nbth].push_back(d); + nb++; + } + map.next(d); + } + sync1.wait(); + for (unsigned int i = 0; i < nbth; ++i) + vd[i].swap(tempo[i]); + sync2.wait(); + } + } + else + { + while (d != map.end()) + { + for (unsigned int i = 0; i < nbth; ++i) + tempo[i].clear(); + unsigned int nb = 0; + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!dmark->isMarked(d))) + { + dmark->markOrbit(d); + tempo[nb%nbth].push_back(d); + nb++; + } + map.next(d); + } + sync1.wait(); + for (unsigned int i = 0; i < nbth; ++i) + vd[i].swap(tempo[i]); + sync2.wait(); } - - sync1.wait(); - for (unsigned int i = 0; i < nbth; ++i) - vd[i].swap(tempo[i]); - sync2.wait(); } sync1.wait(); @@ -316,11 +336,53 @@ void foreach_cell(typename PFP::MAP& map, FunctorMapThreaded& delete[] threads; delete[] vd; delete[] tempo; + + if (cmark != NULL) + delete cmark; + + if (dmark != NULL) + delete dmark; +} + + + +template +void foreach_dart(MAP& map, FunctorMapThreaded& func, unsigned int nbth, bool needMarkers, const FunctorSelect& good) +{ + if (nbth == 0) + nbth = optimalNbThreads(); + + std::vector*> funcs; + funcs.reserve(nbth); + + FunctorMapThreaded* ptr = func.duplicate(); + bool shared = (ptr == NULL); + + if (shared) + { + for (unsigned int i = 0; i < nbth; ++i) + funcs.push_back(&func); + } + else + { + funcs.push_back(ptr); + for (unsigned int i = 1; i < nbth; ++i) + funcs.push_back(func.duplicate()); + } + + foreach_dart(map,funcs,needMarkers,good); + + if (!shared) + for (unsigned int i = 0; i < nbth; ++i) + delete funcs[i]; } -template -void foreach_dart(typename PFP::MAP& map, FunctorMapThreaded& func, unsigned int nbth, unsigned int szbuff, bool needMarkers, const FunctorSelect& good) + +template +void foreach_dart(MAP& map, std::vector*> funcs, bool needMarkers, const FunctorSelect& good) { + unsigned int nbth = funcs.size(); + std::vector* vd = new std::vector[nbth]; boost::thread** threads = new boost::thread*[nbth]; @@ -328,11 +390,11 @@ void foreach_dart(typename PFP::MAP& map, FunctorMapThreaded& // nbth new functions, new thread (with good darts !) for (unsigned int i = 0; i < nbth; ++i) - vd[i].reserve(szbuff); + vd[i].reserve(SIZE_BUFFER_THREAD); // fill each vd buffers with 4096 darts unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { if (good(d)) { @@ -342,32 +404,26 @@ void foreach_dart(typename PFP::MAP& map, FunctorMapThreaded& map.next(d); } - if (needMarkers) - { - // ensure that there is enough threads - unsigned int nbth_prec = map.getNbThreadMarkers(); - if (nbth_prec < nbth+1) - map.addThreadMarker(nbth+1-nbth_prec); - } - boost::barrier sync1(nbth+1); boost::barrier sync2(nbth+1); bool finished = false; // lauch threads if (needMarkers) { - for (unsigned int i = 0; i < nbth; ++i) - threads[i] = new boost::thread(ThreadFunction(func, vd[i],sync1,sync2, finished,1+i)); + unsigned int nbth_prec = map.getNbThreadMarkers(); + if (nbth_prec < nbth+1) + map.addThreadMarker(nbth+1-nbth_prec); } - else + + for (unsigned int i = 0; i < nbth; ++i) { - for (unsigned int i = 0; i < nbth; ++i) - threads[i] = new boost::thread(ThreadFunction(func, vd[i],sync1,sync2, finished,0)); + threads[i] = new boost::thread(ThreadFunction(funcs[i], vd[i],sync1,sync2, finished,1+i)); } + // and continue to traverse the map std::vector* tempo = new std::vector[nbth]; for (unsigned int i = 0; i < nbth; ++i) - tempo[i].reserve(szbuff); + tempo[i].reserve(SIZE_BUFFER_THREAD); while (d != map.end()) { @@ -375,7 +431,7 @@ void foreach_dart(typename PFP::MAP& map, FunctorMapThreaded& tempo[i].clear(); unsigned int nb =0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { if (good(d)) { @@ -407,32 +463,19 @@ void foreach_dart(typename PFP::MAP& map, FunctorMapThreaded& delete tempo; } -template -void foreach_orbit_res(typename PFP::MAP& map, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers, const FunctorSelect& good) -{ - std::vector* vd = new std::vector[nbth]; - boost::thread** threads = new boost::thread*[nbth]; - ThreadFunctionResult** th_funcs= new ThreadFunctionResult*[nbth]; - DartMarker dm(map); - Dart d = map.begin(); +// TODO same modification for transparent usage of dart marker / cell marker / quick traversal ?? - // nbth new functions, new thread (with good darts !) +template +void foreach_cell2Pass(MAP& map, std::vector*>& funcsFrontnBack, unsigned int nbLoops, bool needMarkers, const FunctorSelect& good) +{ + unsigned int nbth = funcsFrontnBack.size()/2; + + std::vector* vd = new std::vector[2*nbth]; for (unsigned int i = 0; i < nbth; ++i) - vd[i].reserve(szbuff); + vd[i].reserve(SIZE_BUFFER_THREAD); - // fill each vd buffers with 4096 darts - unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) - { - if (good(d) && (!dm.isMarked(d))) - { - dm.markOrbit(d); - vd[nb%nbth].push_back(d); - nb++; - } - map.next(d); - } + boost::thread** threadsAB = new boost::thread*[2*nbth]; if (needMarkers) { @@ -442,397 +485,19 @@ void foreach_orbit_res(typename PFP::MAP& map, FunctorMapThreadedResult cm(map); // for 2 pass front mark / back unmark boost::barrier sync1(nbth+1); boost::barrier sync2(nbth+1); - bool finished=false; - // lauch threads - if (needMarkers) - { - for (unsigned int i = 0; i < nbth; ++i) - { - // here dynamic allocation to allow the freeing of m_functor (clean) at the end - th_funcs[i] = new ThreadFunctionResult(func, vd[i],sync1,sync2, finished,1+i,results[i]); - threads[i] = new boost::thread(*(th_funcs[i])); - } - } - else - { - for (unsigned int i = 0; i < nbth; ++i) - { - th_funcs[i] = new ThreadFunctionResult(func, vd[i],sync1,sync2, finished,0,results[i]); - threads[i] = new boost::thread(*(th_funcs[i])); - } - } - - // and continue to traverse the map - std::vector* tempo = new std::vector[nbth]; - - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].reserve(szbuff); - - while (d != map.end()) - { - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].clear(); - - unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) - { - if (good(d) && (!dm.isMarked(d))) - { - dm.markOrbit(d); - tempo[nb%nbth].push_back(d); - nb++; - } - map.next(d); - } - - // sync and swap the two vectors - sync1.wait(); - for (unsigned int i=0; i res; - //wait for all theads to be finished and get results - for (unsigned int i = 0; i < nbth; ++i) - { - threads[i]->join(); - delete threads[i]; - th_funcs[i]->clean(); - } - - //release dynamic allocation - delete[] threads; - delete[] vd; - delete[] th_funcs; - delete[] tempo; -} - -template -void foreach_cell_res(typename PFP::MAP& map, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers, const FunctorSelect& good) -{ - std::vector* vd = new std::vector[nbth]; - boost::thread** threads = new boost::thread*[nbth]; - ThreadFunctionResult** th_funcs= new ThreadFunctionResult*[nbth]; - - CellMarker cm(map); - Dart d = map.begin(); - - // nbth new functions, new thread (with good darts !) - for (unsigned int i = 0; i < nbth; ++i) - vd[i].reserve(szbuff); - - // fill each vd buffers with 4096 darts - unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) - { - if (good(d) && (!cm.isMarked(d))) - { - cm.mark(d); - vd[nb%nbth].push_back(d); - nb++; - } - map.next(d); - } - - if (needMarkers) - { - // ensure that there is enough threads - unsigned int nbth_prec = map.getNbThreadMarkers(); - if (nbth_prec < nbth+1) - map.addThreadMarker(nbth+1-nbth_prec); - } - - // prepare some space pour results - results.resize(nbth); - - boost::barrier sync1(nbth+1); - boost::barrier sync2(nbth+1); - bool finished=false; - // lauch threads - if (needMarkers) - { - for (unsigned int i = 0; i < nbth; ++i) - { - th_funcs[i] = new ThreadFunctionResult(func, vd[i],sync1,sync2, finished,1+i,results[i]); - threads[i] = new boost::thread(*(th_funcs[i])); - } - } - else - { - for (unsigned int i = 0; i < nbth; ++i) - { - th_funcs[i] = new ThreadFunctionResult(func, vd[i],sync1,sync2, finished,0,results[i]); - threads[i] = new boost::thread(*(th_funcs[i])); - } - } - - // and continue to traverse the map - std::vector* tempo = new std::vector[nbth]; - - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].reserve(szbuff); - - while ( d != map.end()) - { - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].clear(); - - unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) - { - if (good(d) && (!cm.isMarked(d))) - { - cm.mark(d); - tempo[nb%nbth].push_back(d); - nb++; - } - map.next(d); - } - - sync1.wait(); - for (unsigned int i=0; i res; - //wait for all theads to be finished and get results - for (unsigned int i = 0; i < nbth; ++i) - { - threads[i]->join(); - delete threads[i]; - th_funcs[i]->clean(); - } - - delete[] threads; - delete[] vd; - delete[] th_funcs; - delete[] tempo; -} - -template -void foreach_dart_res(typename PFP::MAP& map, FunctorMapThreadedResult& func, unsigned int nbth, unsigned int szbuff, std::vector& results, bool needMarkers, const FunctorSelect& good) -{ - std::vector* vd = new std::vector[nbth]; - boost::thread** threads = new boost::thread*[nbth]; - ThreadFunctionResult** th_funcs= new ThreadFunctionResult*[nbth]; - - Dart d = map.begin(); - - // nbth new functions, new thread (with good darts !) - for (unsigned int i=0; i(func, vd[i],sync1,sync2, finished,1+i,results[i]); - threads[i] = new boost::thread(*(th_funcs[i])); - } - } - else - { - for (unsigned int i = 0; i < nbth; ++i) - { - th_funcs[i] = new ThreadFunctionResult(func, vd[i],sync1,sync2, finished,0,results[i]); - threads[i] = new boost::thread(*(th_funcs[i])); - } - } - - // and continue to traverse the map - std::vector* tempo = new std::vector[nbth]; - - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].reserve(szbuff); - - while (d != map.end()) - { - for (unsigned int i=0; i res; - //wait for all theads to be finished and get results - for (unsigned int i = 0; i < nbth; ++i) - { - threads[i]->join(); - delete threads[i]; - th_funcs[i]->clean(); - } - - delete[] threads; - delete[] vd; - delete[] th_funcs; - delete[] tempo; -} - -template -T sumResult(const std::vector& res) -{ - T sum(res.front()); - typename std::vector::const_iterator it = res.begin(); - it++; - while (it != res.end()) - { - sum += *it; - ++it; - } - return sum; -} - -template -std::pair sumPairResult(const std::vector< std::pair >& res) -{ - T1 sum1(res.front().first); - T2 sum2(res.front().second); - typename std::vector< std::pair >::const_iterator it = res.begin(); - it++; - while (it != res.end()) - { - sum1 += it->first; - sum2 += it->second; - ++it; - } - return std::pair(sum1,sum2); -} - -template -T maxResult(const std::vector& res) -{ - T maxr(res.front()); - typename std::vector::const_iterator it = res.begin(); - it++; - while (it != res.end()) - { - if (*it > maxr) - maxr = *it; - ++it; - } - return maxr; -} - -template -T minResult(const std::vector& res) -{ - T minr(res.front()); - typename std::vector::const_iterator it = res.begin(); - it++; - while (it != res.end()) - { - if (*it < minr) - minr = *it; - ++it; - } - return minr; -} - - - - - -/** - * Traverse cells of a map in parallel. Use embedding marker - * Functor application must be independant - * @param map the map - * @param func the functor to apply - * @param nbth number of thread to use (use twice as threads of processor) - * @param szbuff size of buffers to store darts in each thread (default is 8192, use less for lower memory consumsion) - * @param good a selector - */ -template -void foreach_cell2Pass(typename PFP::MAP& map, FunctorMapThreaded& funcFront, FunctorMapThreaded& funcBack, unsigned int nbLoops, unsigned int nbth, unsigned int szbuff, bool needMarkers, const FunctorSelect& good) -{ - std::vector* vd = new std::vector[nbth]; - for (unsigned int i = 0; i < nbth; ++i) - vd[i].reserve(szbuff); - - std::vector* tempo = new std::vector[nbth]; - for (unsigned int i = 0; i < nbth; ++i) - tempo[i].reserve(szbuff); - - boost::thread** threadsA = new boost::thread*[nbth]; - boost::thread** threadsB = new boost::thread*[nbth]; - - if (needMarkers) - { - // ensure that there is enough threads - unsigned int nbth_prec = map.getNbThreadMarkers(); - if (nbth_prec < nbth+1) - map.addThreadMarker(nbth+1-nbth_prec); - } - - CellMarkerNoUnmark cm(map); for (unsigned int loop=0; loop< nbLoops; ++loop) { // PASS FRONT (A) { Dart d = map.begin(); - // fill each vd buffers with szbuff darts + // fill each vd buffers with SIZE_BUFFER_THREAD darts unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { if (good(d) && (!cm.isMarked(d))) { @@ -843,34 +508,23 @@ void foreach_cell2Pass(typename PFP::MAP& map, FunctorMapThreaded(funcFront, vd[i],sync1,sync2, finished,1+i)); - } - else - { - for (unsigned int i = 0; i < nbth; ++i) - threadsA[i] = new boost::thread(ThreadFunction(funcFront, vd[i],sync1,sync2, finished,0)); - } - // and continue to traverse the map + + for (unsigned int i = 0; i < nbth; ++i) + threadsAB[i] = new boost::thread(ThreadFunction(funcsFrontnBack[i], vd[i], sync1, sync2, finished,1+i)); while (d != map.end()) { for (unsigned int i = 0; i < nbth; ++i) - tempo[i].clear(); + vd[nbth+i].clear(); unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { if (good(d) && (!cm.isMarked(d))) { cm.mark(d); - tempo[nb%nbth].push_back(d); + vd[nbth+nb%nbth].push_back(d); nb++; } map.next(d); @@ -878,7 +532,7 @@ void foreach_cell2Pass(typename PFP::MAP& map, FunctorMapThreadedjoin(); + threadsAB[i]->join(); } // PASS BACK (B) { for (unsigned int i = 0; i < nbth; ++i) vd[i].clear(); Dart d = map.begin(); - // fill each vd buffers with szbuff darts + // fill each vd buffers with SIZE_BUFFER_THREAD darts unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { if (good(d) && (cm.isMarked(d))) { @@ -908,34 +562,24 @@ void foreach_cell2Pass(typename PFP::MAP& map, FunctorMapThreaded(funcBack, vd[i],sync1,sync2, finished,1+i)); - } - else - { - for (unsigned int i = 0; i < nbth; ++i) - threadsB[i] = new boost::thread(ThreadFunction(funcBack, vd[i],sync1,sync2, finished,0)); - } + for (unsigned int i = 0; i < nbth; ++i) + threadsAB[nbth+i] = new boost::thread(ThreadFunction(funcsFrontnBack[nbth+i], vd[i],sync1,sync2, finished,1+i)); + // and continue to traverse the map while (d != map.end()) { for (unsigned int i = 0; i < nbth; ++i) - tempo[i].clear(); + vd[nbth+i].clear(); unsigned int nb = 0; - while ((d != map.end()) && (nb < nbth*szbuff) ) + while ((d != map.end()) && (nb < nbth*SIZE_BUFFER_THREAD) ) { if (good(d) && (cm.isMarked(d))) { cm.unmark(d); - tempo[nb%nbth].push_back(d); + vd[nbth+nb%nbth].push_back(d); nb++; } map.next(d); @@ -943,7 +587,7 @@ void foreach_cell2Pass(typename PFP::MAP& map, FunctorMapThreadedjoin(); + threadsAB[nbth+i]->join(); } } // free buffers and threads - for (unsigned int i = 0; i < nbth; ++i) + for (unsigned int i = 0; i < 2*nbth; ++i) { - delete threadsA[i]; - delete threadsB[i]; + delete threadsAB[i]; } - delete[] threadsA; - delete[] threadsB; + delete[] threadsAB; delete[] vd; - delete[] tempo; } +template +void foreach_cell2Pass(MAP& map, FunctorMapThreaded& funcFront, FunctorMapThreaded& funcBack, unsigned int nbLoops, unsigned int nbth, bool needMarkers, const FunctorSelect& good) +{ + if (nbth == 0) + nbth = optimalNbThreads(); + + std::vector*> funcs; + funcs.reserve(nbth); + + FunctorMapThreaded* ptr = funcFront.duplicate(); + bool shared = (ptr == NULL); + + if (shared) + { + for (unsigned int i = 0; i < nbth; ++i) + funcs.push_back(&funcFront); + for (unsigned int i = 0; i < nbth; ++i) + funcs.push_back(&funcBack); + } + else + { + funcs.push_back(ptr); + for (unsigned int i = 1; i < nbth; ++i) + funcs.push_back(funcFront.duplicate()); + for (unsigned int i = 0; i < nbth; ++i) + funcs.push_back(funcBack.duplicate()); + + } + + foreach_cell2Pass(map,funcs,nbLoops,needMarkers,good); + + if (!shared) + for (unsigned int i = 0; i < 2*nbth; ++i) + delete funcs[i]; +} + +// +// +//template +//void Foreach::Foreach(MAP& map, unsigned int nbth): +//m_nbth(nbth) +//{ +// if (m_nbth == 0) +// m_nbth = optimalNbThreads(); +// +// m_funcs.reserve(m_nbth); +// +// m_vd = new std::vector[2*nbth]; +// for (unsigned int i = 0; i < 2*nbth; ++i) +// m_vd[i].reserve(SIZE_BUFFER_THREAD); +//} +// +//template +//Foreach::~Foreach(MAP& map, unsigned int nbth) +//{ +// delete[] m_vd; +//} +// +// +//template +//void Foreach:: clearFunctors() +//{ +// m_funcs.clear(); +//} +// +//template +//void Foreach:: addFunctor(FunctorMapThreaded* funcPtr) +//{ +// m_funcs.push_back(funcPtr); +//} +// +//template +//template +//T* Foreach::getFunctor(unsigned int i) +//{ +// assert(i < m_funcs.size()); +// return dynamic_cast(m_funcs[i]); +//} +// +// +//template +//template +//void Foreach::traverseCell(bool needMarkers, const FunctorSelect& good, unsigned int currentThread) +//{ +// assert(m_funcs.size() == m_nbth); +// +// boost::thread** threads = new boost::thread*[m_nbth]; +// +// AttributeContainer* cont = NULL; +// DartMarker* dmark = NULL; +// CellMarker* cmark = NULL; +// AttributeMultiVector* quickTraversal = m_map.template getQuickTraversal() ; +// +// // fill each vd buffers with SIZE_BUFFER_THREAD darts +// Dart d; +// unsigned int di=0; +// +// if(quickTraversal != NULL) +// { +// cont = &(m_map.template getAttributeContainer()) ; +// +// di = cont->begin(); +// unsigned int nb = 0; +// while ((di != cont->end()) && (nb < m_nbth*SIZE_BUFFER_THREAD) ) +// { +// d = quickTraversal->operator[](di); +// if (good(d)) +// { +// m_vd[nb%m_nbth].push_back(d); +// nb++; +// } +// cont->next(di); +// } +// } +// else +// { +// if(m_map.template isOrbitEmbedded()) +// { +// cmark = new CellMarker(m_map, currentThread) ; +// +// d = m_map.begin(); +// unsigned int nb = 0; +// while ((d != m_map.end()) && (nb < m_nbth*SIZE_BUFFER_THREAD) ) +// { +// if (good(d) && (!m_map.isBoundaryMarked(d)) && (!cmark->isMarked(d))) +// { +// cmark->mark(d); +// m_vd[nb%m_nbth].push_back(d); +// nb++; +// } +// m_map.next(d); +// } +// } +// else +// { +// dmark = new DartMarker(m_map, currentThread) ; +// d = m_map.begin(); +// unsigned int nb = 0; +// while ((d != m_map.end()) && (nb < m_nbth*SIZE_BUFFER_THREAD) ) +// { +// if (good(d) && (!m_map.isBoundaryMarked(d)) && (!dmark->isMarked(d))) +// { +// dmark->markOrbit(d); +// m_vd[nb%m_nbth].push_back(d); +// nb++; +// } +// m_map.next(d); +// } +// } +// } +// +// boost::barrier sync1(m_nbth+1); +// boost::barrier sync2(m_nbth+1); +// bool finished=false; +// // lauch threads +// if (needMarkers) +// { +// unsigned int nbth_prec = m_map.getNbThreadMarkers(); +// if (nbth_prec < m_nbth+1) +// m_map.addThreadMarker(m_nbth+1-nbth_prec); +// } +// +// for (unsigned int i = 0; i < m_nbth; ++i) +// threads[i] = new boost::thread(ThreadFunction(m_funcs[i], m_vd[i],sync1,sync2, finished,1+i)); +// +// +// if (cont) +// { +// while (di != cont->end()) +// { +// for (unsigned int i = 0; i < m_nbth; ++i) +// m_vd[m_nbth+i].clear(); +// unsigned int nb = 0; +// while ((di != cont->end()) && (nb < m_nbth*SIZE_BUFFER_THREAD) ) +// { +// d = quickTraversal->operator[](di); +// if (good(d)) +// { +// m_vd[m_nbth + nb%m_nbth].push_back(d); +// nb++; +// } +// cont->next(di); +// } +// sync1.wait(); +// for (unsigned int i = 0; i < m_nbth; ++i) +// m_vd[i].swap(m_vd[m_nbth+i]); +// sync2.wait(); +// } +// } +// else if (cmark) +// { +// while (d != m_map.end()) +// { +// for (unsigned int i = 0; i < m_nbth; ++i) +// m_vd[m_nbth+i].clear(); +// unsigned int nb = 0; +// while ((d != m_map.end()) && (nb < m_nbth*SIZE_BUFFER_THREAD) ) +// { +// if (good(d) && (!m_map.isBoundaryMarked(d)) && (!cmark->isMarked(d))) +// { +// cmark->mark(d); +// m_vd[m_nbth+nb%m_nbth].push_back(d); +// nb++; +// } +// m_map.next(d); +// } +// sync1.wait(); +// for (unsigned int i = 0; i < m_nbth; ++i) +// m_vd[i].swap(m_vd[m_nbth+i]); +// sync2.wait(); +// } +// } +// else +// { +// while (d != m_map.end()) +// { +// for (unsigned int i = 0; i < m_nbth; ++i) +// m_vd[m_nbth+i].clear(); +// unsigned int nb = 0; +// while ((d != m_map.end()) && (nb < m_nbth*SIZE_BUFFER_THREAD) ) +// { +// if (good(d) && (!m_map.isBoundaryMarked(d)) && (!dmark->isMarked(d))) +// { +// dmark->markOrbit(d); +// m_vd[m_nbth+nb%m_nbth].push_back(d); +// nb++; +// } +// m_map.next(d); +// } +// sync1.wait(); +// for (unsigned int i = 0; i < m_nbth; ++i) +// m_vd[i].swap(m_vd[m_nbth+i]); +// sync2.wait(); +// } +// } +// +// sync1.wait(); +// finished = true; +// sync2.wait(); +// +// //wait for all theads to be finished +// for (unsigned int i = 0; i < m_nbth; ++i) +// { +// threads[i]->join(); +// delete threads[i]; +// } +// delete[] threads; +// delete[] m_vd; +// +// if (cmark != NULL) +// delete cmark; +// +// if (dmark != NULL) +// delete dmark; +//} +// +// + + + +template +void foreach_cell_all_thread(MAP& map, std::vector*>& funcs, bool needMarkers, const FunctorSelect& good, unsigned int currentThread) +{ + unsigned int nbth = funcs.size(); + boost::thread** threads = new boost::thread*[nbth]; + std::vector vd; + vd.reserve(SIZE_BUFFER_THREAD); + + AttributeContainer* cont = NULL; + DartMarker* dmark = NULL; + CellMarker* cmark = NULL; + AttributeMultiVector* quickTraversal = map.template getQuickTraversal() ; + + // fill each vd buffers with SIZE_BUFFER_THREAD darts + Dart d; + unsigned int di=0; + + if(quickTraversal != NULL) + { + cont = &(map.template getAttributeContainer()) ; + di = cont->begin(); + unsigned int nb = 0; + while ((di != cont->end()) && (nb < SIZE_BUFFER_THREAD) ) + { + d = quickTraversal->operator[](di); + if (good(d)) + { + vd.push_back(d); + nb++; + } + cont->next(di); + } + } + else + { + if(map.template isOrbitEmbedded()) + { + cmark = new CellMarker(map, currentThread) ; + d = map.begin(); + unsigned int nb=0; + while ((d != map.end()) && (nb < SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!cmark->isMarked(d))) + { + cmark->mark(d); + vd.push_back(d); + nb++; + } + map.next(d); + } + } + else + { + dmark = new DartMarker(map, currentThread) ; + d = map.begin(); + unsigned int nb=0; + while ((d != map.end()) && (nb < SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!dmark->isMarked(d))) + { + dmark->markOrbit(d); + vd.push_back(d); + nb++; + } + map.next(d); + } + } + } + + boost::barrier sync1(nbth+1); + boost::barrier sync2(nbth+1); + bool finished=false; + // lauch threads + if (needMarkers) + { + unsigned int nbth_prec = map.getNbThreadMarkers(); + if (nbth_prec < nbth+1) + map.addThreadMarker(nbth+1-nbth_prec); + } + + for (unsigned int i = 0; i < nbth; ++i) + threads[i] = new boost::thread(ThreadFunction(funcs[i], vd,sync1,sync2, finished,1+i)); + + // and continue to traverse the map + std::vector tempo; + tempo.reserve(SIZE_BUFFER_THREAD); + + if (cont) + { + while (di != cont->end()) + { + tempo.clear(); + unsigned int nb=0; + while ((di != cont->end()) && (nb < SIZE_BUFFER_THREAD) ) + { + d = quickTraversal->operator[](di); + if (good(d)) + { + tempo.push_back(d); + nb++; + } + cont->next(di); + } + sync1.wait(); + vd.swap(tempo); + sync2.wait(); + } + } + else if (cmark) + { + while (d != map.end()) + { + tempo.clear(); + unsigned int nb=0; + while ((d != map.end()) && (nb < SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!cmark->isMarked(d))) + { + cmark->mark(d); + tempo.push_back(d); + nb++; + } + map.next(d); + } + sync1.wait(); + vd.swap(tempo); + sync2.wait(); + } + } + else + { + while (d != map.end()) + { + tempo.clear(); + unsigned int nb=0; + while ((d != map.end()) && (nb < SIZE_BUFFER_THREAD) ) + { + if (good(d) && (!map.isBoundaryMarked(d)) && (!dmark->isMarked(d))) + { + dmark->markOrbit(d); + tempo.push_back(d); + nb++; + } + map.next(d); + } + sync1.wait(); + vd.swap(tempo); + sync2.wait(); + } + } + + sync1.wait(); + finished = true; + sync2.wait(); + + //wait for all theads to be finished + for (unsigned int i = 0; i < nbth; ++i) + { + threads[i]->join(); + delete threads[i]; + } + delete[] threads; + + if (cmark != NULL) + delete cmark; + + if (dmark != NULL) + delete dmark; +} diff --git a/include/Algo/Render/GL2/colorPerFaceRender.h b/include/Algo/Render/GL2/colorPerFaceRender.h index 75c57488c160db1f3459e71a7ebcba0d67ae759b..83f61d07439db747182e3e4f541b8a64a4611429 100644 --- a/include/Algo/Render/GL2/colorPerFaceRender.h +++ b/include/Algo/Render/GL2/colorPerFaceRender.h @@ -48,7 +48,7 @@ namespace GL2 /** * Class that update VBO to allow the rendering of per face color rendering - * Warning: do not use same position & color VBO than with pervertex rendering ! + * Use with ColorPerVertexShader */ class ColorPerFaceRender { @@ -63,22 +63,36 @@ public: /** * update drawing buffers + * @param vboPosition vbo of positions to update + * @param vboColor vbo of colors to update * @param map the map - * @param positions attribute of position vertices - * @param colorPerFace attribute of color (per face, or per vertex per face) + * @param positions attribute of position vertices + * @param colorPerXXX attribute of color (per face, per vertex per face, per what you want) * @param good selector */ - template + template void updateVBO(Utils::VBO& vboPosition, Utils::VBO& vboColor, typename PFP::MAP& map, - const VertexAttribute& positions, const AttributeHandler& colorPerXXX, const FunctorSelect& good = allDarts) ; + const VertexAttribute& positions, const ATTRIB& colorPerXXX, const FunctorSelect& good = allDarts) ; - template + /** + * update drawing buffers + * @param vboPosition vbo of positions to update + * @param vboNormals vbo of positions to update + * @param vboColor vbo of colors to update + * @param map the map + * @param positions attribute of position vertices + * @param normals attribute of normal vertices + * @param colorPerXXX attribute of color (per face, per vertex per face, per what you want) + * @param good selector + */ + template void updateVBO(Utils::VBO& vboPosition, Utils::VBO& vboNormals, Utils::VBO& vboColor, typename PFP::MAP& map, - const VertexAttribute& positions, const VertexAttribute& normals, const AttributeHandler& colorPerXXX, const FunctorSelect& good = allDarts) ; + const VertexAttribute& positions, const VertexAttribute& normals, const ATTRIB& colorPerXXX, const FunctorSelect& good = allDarts) ; /** * draw + * @param sh shader use to draw (here only ColorPerVertex) */ void draw(Utils::GLSLShader* sh) ; diff --git a/include/Algo/Render/GL2/colorPerFaceRender.hpp b/include/Algo/Render/GL2/colorPerFaceRender.hpp index 62052035951aa320212db389cb0e7af2975931fc..7ba9405f4b387108138536970beef615b0ccc508 100644 --- a/include/Algo/Render/GL2/colorPerFaceRender.hpp +++ b/include/Algo/Render/GL2/colorPerFaceRender.hpp @@ -49,9 +49,9 @@ m_nbTris(0) -template +template void ColorPerFaceRender::updateVBO(Utils::VBO& vboPosition, Utils::VBO& vboColor, typename PFP::MAP& map, - const VertexAttribute& positions, const AttributeHandler& colorPerXXX, const FunctorSelect& good) + const VertexAttribute& positions, const ATTRIB& colorPerXXX, const FunctorSelect& good) { typedef typename PFP::VEC3 VEC3; typedef typename PFP::REAL REAL; @@ -99,9 +99,10 @@ void ColorPerFaceRender::updateVBO(Utils::VBO& vboPosition, Utils::VBO& vboColor } -template +template void ColorPerFaceRender::updateVBO(Utils::VBO& vboPosition, Utils::VBO& vboNormal, Utils::VBO& vboColor, typename PFP::MAP& map, - const VertexAttribute& positions, const VertexAttribute& normals, const AttributeHandler& colorPerXXX, const FunctorSelect& good) + const VertexAttribute& positions, const VertexAttribute& normals, + const ATTRIB& colorPerXXX, const FunctorSelect& good) { typedef typename PFP::VEC3 VEC3; typedef typename PFP::REAL REAL; diff --git a/include/Algo/Render/GL2/explodeVolumeRender.hpp b/include/Algo/Render/GL2/explodeVolumeRender.hpp index f9856e05d35be5307c202894e18f9ae6eac1b2f7..a332fbf665fea8be0b7a8a87ef80c6540a99517c 100644 --- a/include/Algo/Render/GL2/explodeVolumeRender.hpp +++ b/include/Algo/Render/GL2/explodeVolumeRender.hpp @@ -88,7 +88,7 @@ void ExplodeVolumeRender::updateData(typename PFP::MAP& map, const VertexAttribu typedef typename PFP::REAL REAL; VolumeAutoAttribute centerVolumes(map, "centerVolumes"); - Algo::Geometry::computeCentroidVolumes(map, positions, centerVolumes, good); + Algo::Geometry::Parallel::computeCentroidVolumes(map, positions, centerVolumes, good); std::vector buffer; buffer.reserve(16384); @@ -180,7 +180,7 @@ void ExplodeVolumeRender::updateData(typename PFP::MAP& map, const VertexAttribu typedef typename PFP::REAL REAL; VolumeAutoAttribute centerVolumes(map, "centerVolumes"); - Algo::Geometry::computeCentroidVolumes(map, positions, centerVolumes, good); + Algo::Geometry::Parallel::computeCentroidVolumes(map, positions, centerVolumes, good); std::vector buffer; buffer.reserve(16384); diff --git a/include/Algo/Render/GL2/topo3Render.hpp b/include/Algo/Render/GL2/topo3Render.hpp index 2071fda430a3237dd4d518316f010e3d4f8b3713..e0f290855dfe0fa683506c4e85842d9e204e78fb 100644 --- a/include/Algo/Render/GL2/topo3Render.hpp +++ b/include/Algo/Render/GL2/topo3Render.hpp @@ -81,7 +81,8 @@ void Topo3Render::updateDataMap3(typename PFP::MAP& mapx, const VertexAttribute< CellMarker cmv(mapx); VolumeAutoAttribute centerVolumes(mapx, "centerVolumes"); - Algo::Geometry::computeCentroidVolumes(mapx, positions, centerVolumes, allDarts); + Algo::Geometry::Parallel::computeCentroidVolumes(mapx, positions, centerVolumes, allDarts,3); + // debut phi1 DartAutoAttribute fv1(mapx); @@ -335,7 +336,7 @@ void Topo3Render::updateDataGMap3(typename PFP::MAP& mapx, const VertexAttribute // compute center of each volumes VolumeAutoAttribute centerVolumes(mapx, "centerVolumes"); - Algo::Geometry::computeCentroidVolumes(mapx, positions, centerVolumes, good); + Algo::Geometry::Parallel::computeCentroidVolumes(mapx, positions, centerVolumes, good); // beta1 DartAutoAttribute fv1(mapx); diff --git a/include/Algo/Selection/collector.h b/include/Algo/Selection/collector.h index 26d87cf841b6168b23173e96ff10e90720c80a54..afe325dfe5c78f4129e48e79edbaf52d83e1690c 100644 --- a/include/Algo/Selection/collector.h +++ b/include/Algo/Selection/collector.h @@ -25,6 +25,8 @@ #ifndef __COLLECTOR_H__ #define __COLLECTOR_H__ +#include "Container/fakeAttribute.h" + /***************************************** * Class hierarchy : * Collector (virtual) @@ -53,6 +55,7 @@ protected: typedef typename PFP::REAL REAL; typename PFP::MAP& map; + unsigned int m_thread; Dart centerDart; @@ -62,7 +65,7 @@ protected: std::vector border; public: - Collector(typename PFP::MAP& m); + Collector(typename PFP::MAP& m, unsigned int thread =0); inline void init(Dart d) { @@ -122,9 +125,8 @@ template class Collector_OneRing : public Collector { public: - Collector_OneRing(typename PFP::MAP& m) : - Collector(m) - {} + Collector_OneRing(typename PFP::MAP& m, unsigned int thread=0): + Collector(m, thread) {} void collectAll(Dart d); void collectBorder(Dart d); }; @@ -147,8 +149,8 @@ protected: typename PFP::REAL area; public: - Collector_WithinSphere(typename PFP::MAP& m, const VertexAttribute& p, typename PFP::REAL r = 0) : - Collector(m), + Collector_WithinSphere(typename PFP::MAP& m, const VertexAttribute& p, typename PFP::REAL r = 0, unsigned int thread=0) : + Collector(m, thread), position(p), radius(r), area(0) @@ -184,8 +186,9 @@ public: Collector_NormalAngle( typename PFP::MAP& m, const VertexAttribute& n, - typename PFP::REAL a - ) : Collector(m), normal(n), angleThreshold(a) + typename PFP::REAL a, + unsigned int thread=0 + ) : Collector(m,thread), normal(n), angleThreshold(a) {} inline void setAngleThreshold(typename PFP::REAL a) { angleThreshold = a; } inline typename PFP::REAL getAngleThreshold() const { return angleThreshold; } @@ -215,8 +218,9 @@ public: Collector_NormalAngle_Triangles( typename PFP::MAP& m, const FaceAttribute& n, - typename PFP::REAL a - ) : Collector(m), normal(n), angleThreshold(a) + typename PFP::REAL a, + unsigned int thread=0 + ) : Collector(m,thread), normal(n), angleThreshold(a) {} inline void setAngleThreshold(typename PFP::REAL a) { angleThreshold = a; } inline typename PFP::REAL getAngleThreshold() const { return angleThreshold; } @@ -254,8 +258,8 @@ protected: std::multimap front ; public: - Collector_Dijkstra(typename PFP::MAP& m, const VertexAttribute& p, typename PFP::REAL d = 0) : - Collector(m), + Collector_Dijkstra(typename PFP::MAP& m, const VertexAttribute& p, typename PFP::REAL d = 0, unsigned int thread=0) : + Collector(m,thread), position(p), maxDist(d) { diff --git a/include/Algo/Selection/collector.hpp b/include/Algo/Selection/collector.hpp index a47b3e41e0340404b8ae0f2f408514c55615861f..3d010d820ba28863c62ba4afcc4874d785e1cfff 100644 --- a/include/Algo/Selection/collector.hpp +++ b/include/Algo/Selection/collector.hpp @@ -40,7 +40,7 @@ namespace Selection *********************************************************/ template -Collector::Collector(typename PFP::MAP& m) : map(m) +Collector::Collector(typename PFP::MAP& m, unsigned int thread) : map(m), m_thread(thread) {} template @@ -150,9 +150,9 @@ void Collector_WithinSphere::collectAll(Dart d) this->insideFaces.reserve(32); this->border.reserve(32); - CellMarkerStore vm(this->map); // mark the collected inside-vertices - CellMarkerStore em(this->map); // mark the collected inside-edges + border-edges - CellMarkerStore fm(this->map); // mark the collected inside-faces + border-faces + CellMarkerStore vm(this->map, this->m_thread); // mark the collected inside-vertices + CellMarkerStore em(this->map, this->m_thread); // mark the collected inside-edges + border-edges + CellMarkerStore fm(this->map, this->m_thread); // mark the collected inside-faces + border-faces this->insideVertices.push_back(this->centerDart); vm.mark(this->centerDart); @@ -212,8 +212,8 @@ void Collector_WithinSphere::collectBorder(Dart d) this->border.reserve(128); this->insideVertices.reserve(128); - CellMarkerStore vm(this->map); // mark the collected inside-vertices - CellMarkerStore em(this->map); // mark the collected inside-edges + border-edges + CellMarkerStore vm(this->map, this->m_thread); // mark the collected inside-vertices + CellMarkerStore em(this->map, this->m_thread); // mark the collected inside-edges + border-edges this->insideVertices.push_back(this->centerDart); vm.mark(this->centerDart); @@ -296,9 +296,9 @@ void Collector_NormalAngle::collectAll(Dart d) this->insideFaces.reserve(32); this->border.reserve(32); - CellMarkerStore vm(this->map); // mark the collected inside-vertices - CellMarkerStore em(this->map); // mark the collected inside-edges + border-edges - CellMarkerStore fm(this->map); // mark the collected inside-faces + border-faces + CellMarkerStore vm(this->map, this->m_thread); // mark the collected inside-vertices + CellMarkerStore em(this->map, this->m_thread); // mark the collected inside-edges + border-edges + CellMarkerStore fm(this->map, this->m_thread); // mark the collected inside-faces + border-faces this->insideVertices.push_back(this->centerDart); vm.mark(this->centerDart); @@ -361,8 +361,8 @@ void Collector_NormalAngle::collectBorder(Dart d) this->border.reserve(128); this->insideVertices.reserve(128); - CellMarkerStore vm(this->map); // mark the collected inside-vertices - CellMarkerStore em(this->map); // mark the collected inside-edges + border-edges + CellMarkerStore vm(this->map, this->m_thread); // mark the collected inside-vertices + CellMarkerStore em(this->map, this->m_thread); // mark the collected inside-edges + border-edges this->insideVertices.push_back(this->centerDart); vm.mark(this->centerDart); @@ -419,8 +419,8 @@ void Collector_NormalAngle_Triangles::collectAll(Dart d) this->insideFaces.reserve(32); this->border.reserve(32); - CellMarkerStore fm(this->map); // mark the collected inside-faces + front-faces - CellMarkerStore fminside(this->map); // mark the collected inside-faces + CellMarkerStore fm(this->map, this->m_thread); // mark the collected inside-faces + front-faces + CellMarkerStore fminside(this->map, this->m_thread); // mark the collected inside-faces std::queue front; front.push(this->centerDart); @@ -450,8 +450,8 @@ void Collector_NormalAngle_Triangles::collectAll(Dart d) } } - CellMarkerStore vm(this->map); // mark inside-vertices and border-vertices - CellMarkerStore em(this->map); // mark inside-edges and border-edges + CellMarkerStore vm(this->map, this->m_thread); // mark inside-vertices and border-vertices + CellMarkerStore em(this->map, this->m_thread); // mark inside-edges and border-edges std::vector::iterator f_it; for (f_it = this->insideFaces.begin(); f_it != this->insideFaces.end(); f_it++) { // collect insideVertices, insideEdges, and border @@ -502,8 +502,8 @@ void Collector_NormalAngle_Triangles::collectBorder(Dart d) this->insideFaces.reserve(32); this->border.reserve(32); - CellMarkerStore fm(this->map); // mark the collected inside-faces + front-faces - CellMarkerStore fminside(this->map); // mark the collected inside-faces + CellMarkerStore fm(this->map, this->m_thread); // mark the collected inside-faces + front-faces + CellMarkerStore fminside(this->map, this->m_thread); // mark the collected inside-faces std::queue front; front.push(this->centerDart); @@ -533,7 +533,7 @@ void Collector_NormalAngle_Triangles::collectBorder(Dart d) } } - CellMarkerStore em(this->map); // mark inside-edges and border-edges + CellMarkerStore em(this->map, this->m_thread); // mark inside-edges and border-edges std::vector::iterator f_it; for (f_it = this->insideFaces.begin(); f_it != this->insideFaces.end(); f_it++) { // collect border (edges) @@ -558,10 +558,11 @@ void Collector_NormalAngle_Triangles::collectBorder(Dart d) *********************************************************/ template -void Collector_Dijkstra::collectAll(Dart dinit){ +void Collector_Dijkstra::collectAll(Dart dinit) +{ init(dinit); - CellMarkerStore vmReached (this->map); + CellMarkerStore vmReached (this->map, this->m_thread); vertexInfo[this->centerDart].it = front.insert(std::pair(0.0, this->centerDart)); vertexInfo[this->centerDart].valid = true; vmReached.mark(this->centerDart); @@ -608,8 +609,8 @@ void Collector_Dijkstra::collectAll(Dart dinit){ } - CellMarkerStore em (this->map); - CellMarkerStore fm (this->map); + CellMarkerStore em (this->map, this->m_thread); + CellMarkerStore fm (this->map, this->m_thread); for (std::vector::iterator e_it = this->insideVertices.begin(); e_it != this->insideVertices.end() ; e_it++) { // collect insideEdges @@ -643,10 +644,11 @@ void Collector_Dijkstra::collectAll(Dart dinit){ } template -void Collector_Dijkstra::collectBorder(Dart dinit){ +void Collector_Dijkstra::collectBorder(Dart dinit) +{ init(dinit); - CellMarkerStore vmReached (this->map); + CellMarkerStore vmReached (this->map, this->m_thread); vertexInfo[this->centerDart].it = front.insert(std::pair(0.0, this->centerDart)); vertexInfo[this->centerDart].valid = true; vmReached.mark(this->centerDart); @@ -693,7 +695,7 @@ void Collector_Dijkstra::collectBorder(Dart dinit){ } - CellMarkerStore fm (this->map); + CellMarkerStore fm (this->map, this->m_thread); for (std::vector::iterator e_it = this->insideVertices.begin(); e_it != this->insideVertices.end() ; e_it++) { // collect border @@ -715,7 +717,8 @@ void Collector_Dijkstra::collectBorder(Dart dinit){ } template -inline float Collector_Dijkstra::edgeLength (Dart d){ +inline float Collector_Dijkstra::edgeLength (Dart d) +{ typename PFP::VEC3 v = Algo::Geometry::vectorOutOfDart(this->map, d, this->position); return v.norm(); } diff --git a/include/Algo/Selection/raySelectFunctor.hpp b/include/Algo/Selection/raySelectFunctor.hpp index 96b19e7ec7ef458d8ad341af56f5737b6d811a97..3faa69947f5fd95989acd27b968260921bc38484 100644 --- a/include/Algo/Selection/raySelectFunctor.hpp +++ b/include/Algo/Selection/raySelectFunctor.hpp @@ -221,147 +221,8 @@ public: } }; -/** - * Order relation between Darts with respect to the depth of - * their 0-embedding - * - * Used in a std::sort algorithm - */ -//template -//class DartDepthOrdering -//{ -// typedef typename PFP::MAP MAP; -//// typedef typename PFP::EMB EMB; -// -// -//protected: -// MAP& m_map; -// const typename PFP::VEC3& m_A; -// VertexAttribute& m_positions; -//public: -// DartDepthOrdering(MAP& map, unsigned int idPos, const typename PFP::VEC3& A): -// m_map(map), m_A(A), m_positions(idPos,map) {} -// -// bool operator()(const Dart& d, const Dart& e) -// { -// typename PFP::VEC3 P = m_positions[d]; //m_map.getVertexEmb(d)->getPosition(); -// P -= m_A; -// typename PFP::REAL ld = P*P;// l^2 -// -// P = m_positions[e]; //m_map.getVertexEmb(e)->getPosition(); -// P -= m_A; -// typename PFP::REAL le = P*P;// l^2 -// -// if (ld < le) -// return true; -// return false; -// } -//}; -/** - * Order relation between Darts with respect to the distance of - * their 0-embedding to the line given in parameter in the constructor - * - * Used in a std::sort algorithm - */ -//template -//class DartRayDistanceOrdering -//{ -// typedef typename PFP::MAP MAP ; -//// typedef typename PFP::EMB EMB ; -// -// -//protected: -// MAP& m_map ; -// const typename PFP::VEC3& m_A ; -// const typename PFP::VEC3& m_AB ; -// float m_AB2 ; -// VertexAttribute& m_positions; -// -//public: -// DartRayDistanceOrdering(MAP& map, unsigned int idPos, const typename PFP::VEC3& A, const typename PFP::VEC3& AB) : -// m_map(map), m_A(A), m_AB(AB), m_positions(idPos,map) -// { -// m_AB2 = m_AB*m_AB ; // l^2 -// } -// -// bool operator()(const Dart& d, const Dart& e) -// { -// typename PFP::VEC3 P = m_positions[d]; //m_map.getVertexEmb(d)->getPosition() ; -// float ld = Geom::squaredDistanceLine2Point(m_A, m_AB, m_AB2, P) ; -// P = m_positions[e]; //m_map.getVertexEmb(e)->getPosition() ; -// float le = Geom::squaredDistanceLine2Point(m_A, m_AB, m_AB2, P) ; -// -// if (ld < le) -// return true; -// return false; -// } -//}; -/** - * Order relation between Darts with respect to the depth - * of their faces : - * f1 < f2 if f1 contains the vertex whose 0-embedding is the closest - * - * Used in a std::sort algorithm - */ -//template -//class FaceDepthOrdering -//{ -// typedef typename PFP::MAP MAP ; -// -// -//protected: -// MAP& m_map ; -// const typename PFP::VEC3& m_A ; -// VertexAttribute& m_positions; -// std::vector& m_faces; -// -//public: -// FaceDepthOrdering(MAP& map, unsigned int idPos, const typename PFP::VEC3& A, std::vector& faces) : m_map(map), m_A(A), m_positions(idPos,map), m_faces(faces) {} -// -//// bool operator()(const Dart& d, const Dart& e) -// bool operator()(Dart d, Dart e) -// { -// for (typename std::vector::iterator it = m_faces.begin(); it != m_faces.end(); ++it) -// { -// CGoGNout << "Dart: "<< (it - m_faces.begin()) <<" = " << (*it)->getLabel()<getLabel() <<" ?? "<< e->getLabel()<getPosition() ; -// P -= m_A ; -// typename PFP::REAL minDist = P*P ; -// Dart closestD = d ; -// Dart it = d ; -// do -// { -// P = m_positions[it]; //m_map.getVertexEmb(it)->getPosition() ; // compute the minimum -// P -= m_A ; // distance among the vertices -// typename PFP::REAL dist = P*P ; // of the face of d -// if(dist < minDist) -// minDist = dist ; -// it = m_map.phi1(it) ; -// } while(it != d) ; -// it = e ; -// do -// { -// P = m_positions[it]; //m_map.getVertexEmb(it)->getPosition() ; // if one vertex of the face -// P -= m_A ; // of e is closer than the previous -// typename PFP::REAL dist = P*P ; // minimum, then e < d -// if(dist < minDist) // else, d < e -// return false ; -// it = m_map.phi1(it) ; -// } while(it != e) ; -// -// CGoGNout << "end sort op"< bool distndartOrdering(const std::pair& e1, const std::pair& e2) @@ -375,6 +236,148 @@ bool distnintOrdering(const std::pair& e1, con return (e1.first < e2.first); } + + + +namespace Parallel +{ + +template +class FuncVertexInter: public FunctorMapThreaded +{ + typedef typename PFP::MAP MAP; + +protected: + const VertexAttribute& m_positions; + const typename PFP::VEC3& m_A; + const typename PFP::VEC3& m_AB; + float m_AB2; + float m_distMax; + std::vector > m_vd; + +public: + FuncVertexInter(MAP& map, const VertexAttribute& position, const typename PFP::VEC3& A, const typename PFP::VEC3& AB, typename PFP::REAL AB2, typename PFP::REAL dm2): + FunctorMapThreaded(map), m_positions(position), m_A(A), m_AB(AB), m_AB2(AB2), m_distMax(dm2) + {} + + void run(Dart d, unsigned int thread) + { + const typename PFP::VEC3& P = m_positions[d]; + float dist = Geom::squaredDistanceLine2Point(m_A, m_AB, m_AB2, P); + if (dist < m_distMax) + { + typename PFP::REAL distA = (P-m_A).norm2(); + m_vd.push_back(std::pair(distA,d)); + } + + } + + const std::vector >& getVertexDistances() { return m_vd;} +}; + + +template +class FuncEdgeInter: public FunctorMapThreaded +{ + typedef typename PFP::MAP MAP; + +protected: + const VertexAttribute& m_positions; + const typename PFP::VEC3& m_A; + const typename PFP::VEC3& m_AB; + float m_AB2; + float m_distMax; + std::vector > m_ed; + +public: + FuncEdgeInter(MAP& map, const VertexAttribute& position, const typename PFP::VEC3& A, const typename PFP::VEC3& AB, typename PFP::REAL AB2, typename PFP::REAL dm2): + FunctorMapThreaded(map), m_positions(position), m_A(A), m_AB(AB), m_AB2(AB2), m_distMax(dm2) + {} + + void run(Dart d, unsigned int thread) + { + // get back position of segment PQ + const typename PFP::VEC3& P = m_positions[d]; + Dart dd = this->m_map.phi1(d); + const typename PFP::VEC3& Q = m_positions[dd]; + // the three distance to P, Q and (PQ) not used here + float dist = Geom::squaredDistanceLine2Seg(m_A, m_AB, m_AB2, P, Q); + if (dist < m_distMax) + { + typename PFP::VEC3 M = (P+Q)/2.0; + typename PFP::REAL distA = (M-m_A).norm2(); + m_ed.push_back(std::pair(distA,d)); + } + } + + const std::vector >& getEdgeDistances() { return m_ed;} +}; + + + +template +class FuncFaceInter: public FunctorMapThreaded +{ + typedef typename PFP::MAP MAP; + +protected: + const VertexAttribute& m_positions; + const typename PFP::VEC3& m_A; + const typename PFP::VEC3& m_AB; + std::vector > m_fd; + +public: + FuncFaceInter(MAP& map, const VertexAttribute& position, const typename PFP::VEC3& A, const typename PFP::VEC3& AB): + FunctorMapThreaded(map), m_positions(position), m_A(A), m_AB(AB) + {} + + void run(Dart d, unsigned int thread) + { + const typename PFP::VEC3& Ta = m_positions[d]; + + Dart dd = this->m_map.phi1(d); + Dart ddd = this->m_map.phi1(dd); + bool notfound = true; + do + { + // get back position of triangle Ta,Tb,Tc + const typename PFP::VEC3& Tb = m_positions[dd]; + const typename PFP::VEC3& Tc = m_positions[ddd]; + typename PFP::VEC3 I; + if (Geom::intersectionRayTriangleOpt(m_A, m_AB, Ta, Tb, Tc, I)) + { + typename PFP::REAL dist = (I-m_A).norm2(); + m_fd.push_back(std::pair(dist,d)); + notfound = false; + } + // next triangle if we are in polygon + dd = ddd; + ddd = this->m_map.phi1(dd); + } while ((ddd != d) && notfound); + } + + const std::vector >& getFaceDistances() { return m_fd;} +}; + + + + +} + + + + + + + + + + + + + + + } //namespace Selection } //namespace Algo diff --git a/include/Algo/Selection/raySelector.h b/include/Algo/Selection/raySelector.h index 2192321e2b25fabc964b11b021a19b01431eff5d..90a65bef2a9bbbb8af9b0afa859dfef0adc97303 100644 --- a/include/Algo/Selection/raySelector.h +++ b/include/Algo/Selection/raySelector.h @@ -28,6 +28,7 @@ #include #include #include "Algo/Selection/raySelectFunctor.hpp" +#include "Algo/Parallel/parallel_foreach.h" namespace CGoGN { @@ -165,6 +166,160 @@ void verticesRaySelection(typename PFP::MAP& map, const VertexAttribute +void facesRaySelection(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& good, const typename PFP::VEC3& rayA, const typename PFP::VEC3& rayAB, std::vector& vecFaces, unsigned int nbth=0, unsigned int current_thread=0) +{ + if (nbth==0) +// nbth = Algo::Parallel::optimalNbThreads(); + nbth =2; // seems to be optimal ? + + std::vector*> functs; + for (unsigned int i=0; i < nbth; ++i) + functs.push_back(new Parallel::FuncFaceInter(map,position,rayA, rayAB)); + + Algo::Parallel::foreach_cell(map, functs, false, good, current_thread); + + + // compute total nb of intersection + unsigned int nbtot=0; + for (unsigned int i=0; i < nbth; ++i) + nbtot += static_cast*>(functs[i])->getFaceDistances().size(); + + std::vector > distndart; + distndart.reserve(nbtot); + for (unsigned int i=0; i < nbth; ++i) + { + distndart.insert(distndart.end(),static_cast*>(functs[i])->getFaceDistances().begin(), static_cast*>(functs[i])->getFaceDistances().end() ); + delete functs[i]; + } + + // sort the vector of pair dist/dart + std::sort(distndart.begin(), distndart.end(), distndartOrdering); + + vecFaces.clear(); + vecFaces.reserve(nbtot); + // store sorted darts in returned vector + for (unsigned int i = 0; i < nbtot; ++i) + vecFaces.push_back(distndart[i].second); +} + +template +void edgesRaySelection(typename PFP::MAP& map, const VertexAttribute& position, const FunctorSelect& good, const typename PFP::VEC3& rayA, const typename PFP::VEC3& rayAB, std::vector& vecEdges, float dist, unsigned int nbth=0, unsigned int current_thread=0) +{ + typename PFP::REAL dist2 = dist * dist; + typename PFP::REAL AB2 = rayAB * rayAB; + + if (nbth==0) +// nbth = Algo::Parallel::optimalNbThreads(); + nbth =2; // seems to be optimal ? + + std::vector*> functs; + for (unsigned int i=0; i < nbth; ++i) + functs.push_back(new Parallel::FuncEdgeInter(map,position,rayA, rayAB, AB2, dist2)); + + Algo::Parallel::foreach_cell(map, functs, false, good, current_thread); + + // compute total nb of intersection + unsigned int nbtot=0; + for (unsigned int i=0; i < nbth; ++i) + nbtot += static_cast*>(functs[i])->getEdgeDistances().size(); + + std::vector > distndart; + distndart.reserve(nbtot); + for (unsigned int i=0; i < nbth; ++i) + { + distndart.insert(distndart.end(),static_cast*>(functs[i])->getEdgeDistances().begin(), static_cast*>(functs[i])->getEdgeDistances().end() ); + delete functs[i]; + } + + // sort the vector of pair dist/dart + std::sort(distndart.begin(), distndart.end(), distndartOrdering); + + // store sorted darts in returned vector + vecEdges.clear(); + vecEdges.reserve(nbtot); + for (unsigned int i = 0; i < nbtot; ++i) + vecEdges.push_back(distndart[i].second); +} + + +template +void verticesRaySelection(typename PFP::MAP& map, const VertexAttribute& position, const typename PFP::VEC3& rayA, const typename PFP::VEC3& rayAB, std::vector& vecVertices, float dist, const FunctorSelect& good= allDarts, unsigned int nbth=0, unsigned int current_thread=0) +{ + typename PFP::REAL dist2 = dist * dist; + typename PFP::REAL AB2 = rayAB * rayAB; + + if (nbth==0) +// nbth = Algo::Parallel::optimalNbThreads(); + nbth =2; // seems to be optimal ? + + std::vector*> functs; + for (unsigned int i=0; i < nbth; ++i) + functs.push_back(new Parallel::FuncVertexInter(map,position,rayA, rayAB, AB2, dist2)); + + Algo::Parallel::foreach_cell(map, functs, false, good, current_thread); + + // compute total nb of intersection + unsigned int nbtot=0; + for (unsigned int i=0; i < nbth; ++i) + nbtot += static_cast*>(functs[i])->getVertexDistances().size(); + + std::vector > distndart; + distndart.reserve(nbtot); + for (unsigned int i=0; i < nbth; ++i) + { + distndart.insert(distndart.end(),static_cast*>(functs[i])->getVertexDistances().begin(), static_cast*>(functs[i])->getVertexDistances().end() ); + delete functs[i]; + } + + // sort the vector of pair dist/dart + std::sort(distndart.begin(), distndart.end(), distndartOrdering); + + // store sorted darts in returned vector + vecVertices.clear(); + vecVertices.reserve(nbtot); + for (unsigned int i = 0; i < nbtot; ++i) + vecVertices.push_back(distndart[i].second); + + +} + +template +void vertexRaySelection(typename PFP::MAP& map, const VertexAttribute& position, const typename PFP::VEC3& rayA, const typename PFP::VEC3& rayAB, Dart& vertex, const FunctorSelect& good = allDarts, unsigned int nbth=0, unsigned int current_thread=0) +{ + std::vector vecFaces; + vecFaces.reserve(100); + Parallel::facesRaySelection(map, position, good, rayA, rayAB, vecFaces, nbth, current_thread); + + if(vecFaces.size() > 0) + { + // recuperation du sommet le plus proche + Dart d = vecFaces.front(); + Dart it = d; + typename PFP::REAL minDist = (rayA - position[it]).norm2(); + vertex = it; + it = map.phi1(it); + while(it != d) + { + typename PFP::REAL dist = (rayA - position[it]).norm2(); + if(dist < minDist) + { + minDist = dist; + vertex = it; + } + it = map.phi1(it); + } + } + else + vertex = NIL; +} + +} + /** * Function that does the selection of one vertex * @param map the map we want to test diff --git a/include/Container/attributeContainer.hpp b/include/Container/attributeContainer.hpp index d7605cce3cd01ecb68fe02f5b59eecd73c8b5400..935cd9557ce19f2149a5f6d9db7b6edb7c5d672f 100644 --- a/include/Container/attributeContainer.hpp +++ b/include/Container/attributeContainer.hpp @@ -149,7 +149,7 @@ bool AttributeContainer::removeAttribute(const std::string& attribName) if (index == UNKNOWN) { - std::cerr << "removeAttribute by name: attribute not found" << std::endl ; + std::cerr << "removeAttribute by name: attribute not found (" << attribName << ")"<< std::endl ; return false ; } diff --git a/include/Container/registered.h b/include/Container/registered.h index 78eeef8d293574dd684744f16f20431f525df804..67f881aeb6e0f759cf791f0a439f1fc35ecf6448 100644 --- a/include/Container/registered.h +++ b/include/Container/registered.h @@ -37,6 +37,8 @@ protected: std::string m_name; // TODO inutile ?? public: + + virtual ~RegisteredBaseAttribute() {} /** * affecte un nom de type a l'attribut */ diff --git a/include/Geometry/inclusion.hpp b/include/Geometry/inclusion.hpp index a29910108954d1c547222ee8de441767aa5252ab..62a71c04dbf361fab5d93ebade8070718ad4564a 100644 --- a/include/Geometry/inclusion.hpp +++ b/include/Geometry/inclusion.hpp @@ -169,7 +169,7 @@ bool arePointsEquals(const VEC& point1, const VEC& point2) { VEC v(point1 - point2); -#define PRECISION 1e-3 +#define PRECISION 1e-10 return v.norm2() <= PRECISION ; #undef PRECISION } diff --git a/include/Topology/generic/attribmap.hpp b/include/Topology/generic/attribmap.hpp index dd215c35b38cc9067de5d9ee56f95b4ec6999a32..54daf317d10cb7ec98bf74e7ace31feea38ed0f2 100644 --- a/include/Topology/generic/attribmap.hpp +++ b/include/Topology/generic/attribmap.hpp @@ -38,7 +38,7 @@ template inline bool AttribMap::removeAttribute(AttributeHandler& attr) { assert(attr.isValid() || !"Invalid attribute handler") ; - if(m_attribs[attr.getOrbit()].removeAttribute(attr.getIndex())) + if(m_attribs[attr.getOrbit()].template removeAttribute(attr.getIndex())) { typedef std::multimap::iterator IT ; std::pair bounds = attributeHandlers.equal_range(attr.getDataVector()) ; diff --git a/include/Topology/generic/attributeHandler.hpp b/include/Topology/generic/attributeHandler.hpp index 61d70a586e1d7fe08d0c0ed329feb46d0e2b3d43..9339ef65c71d845eed570b82b31ee020f1790067 100644 --- a/include/Topology/generic/attributeHandler.hpp +++ b/include/Topology/generic/attributeHandler.hpp @@ -28,6 +28,7 @@ namespace CGoGN template inline void AttributeHandler::registerInMap() { + boost::mutex::scoped_lock lockAH(m_map->attributeHandlersMutex); m_map->attributeHandlers.insert(std::pair(m_attrib, this)) ; } @@ -35,6 +36,8 @@ template inline void AttributeHandler::unregisterFromMap() { typedef std::multimap::iterator IT ; + + boost::mutex::scoped_lock lockAH(m_map->attributeHandlersMutex); std::pair bounds = m_map->attributeHandlers.equal_range(m_attrib) ; for(IT i = bounds.first; i != bounds.second; ++i) { diff --git a/include/Topology/generic/cellmarker.h b/include/Topology/generic/cellmarker.h index c0726efbe733d57734be5f8019bfd8ac6cc35797..7f1907429f773c866ec39b932321f15908f48271 100644 --- a/include/Topology/generic/cellmarker.h +++ b/include/Topology/generic/cellmarker.h @@ -95,7 +95,7 @@ public: map.addEmbedding() ; m_mark = m_map.getMarkerSet(m_thread).getNewMark() ; m_markVector = m_map.getMarkVector(m_thread) ; - m_map.cellMarkers.push_back(this) ; + m_map.cellMarkers[m_thread].push_back(this) ; } virtual ~CellMarkerBase() @@ -103,12 +103,14 @@ public: if(releaseOnDestruct) { m_map.getMarkerSet(m_thread).releaseMark(m_mark) ; - for(std::vector::iterator it = m_map.cellMarkers.begin(); it != m_map.cellMarkers.end(); ++it) + + std::vector& cmg = m_map.cellMarkers[m_thread]; + for(std::vector::iterator it = cmg.begin(); it != cmg.end(); ++it) { if(*it == this) { - *it = m_map.cellMarkers.back(); - m_map.cellMarkers.pop_back(); + *it = cmg.back(); + cmg.pop_back(); return; } } diff --git a/include/Topology/generic/dartmarker.h b/include/Topology/generic/dartmarker.h index 4a93be2ef63aba78acd317c77ee418813a7e370d..0209f0968242c70565183a5897ecaa156bd8991a 100644 --- a/include/Topology/generic/dartmarker.h +++ b/include/Topology/generic/dartmarker.h @@ -46,6 +46,7 @@ protected: Mark m_mark ; AttributeMultiVector* m_markVector ; unsigned int m_thread ; + unsigned int m_idReg ; bool releaseOnDestruct ; public: @@ -57,7 +58,7 @@ public: { m_mark = m_map.getMarkerSet(m_thread).getNewMark() ; m_markVector = m_map.getMarkVector(m_thread) ; - m_map.dartMarkers.push_back(this) ; + m_map.dartMarkers[m_thread].push_back(this) ; } virtual ~DartMarkerGen() @@ -65,12 +66,13 @@ public: if(releaseOnDestruct) { m_map.getMarkerSet(m_thread).releaseMark(m_mark) ; - for(std::vector::iterator it = m_map.dartMarkers.begin(); it != m_map.dartMarkers.end(); ++it) + std::vector& dmg = m_map.dartMarkers[m_thread]; + for(std::vector::iterator it = dmg.begin(); it != dmg.end(); ++it) { if(*it == this) { - *it = m_map.dartMarkers.back(); - m_map.dartMarkers.pop_back(); + *it = dmg.back(); + dmg.pop_back(); return; } } diff --git a/include/Topology/generic/functor.h b/include/Topology/generic/functor.h index 8a0112a09cb1cf7682fb8031f6e7054481c37e55..5dc40a4f29b28d33fc1bf610c2753e8f6b53d0be 100644 --- a/include/Topology/generic/functor.h +++ b/include/Topology/generic/functor.h @@ -432,6 +432,65 @@ public: } ; + +// +// FOR PARALLEL TRAVERSALS +// + +/** + * Functor class for parallel::foreach_orbit/cell/dart + * Overload run + * Overload duplicate if necessary (no sharing of functors) + */ +template +class FunctorMapThreaded +{ +protected: + MAP& m_map ; + +public: + FunctorMapThreaded(MAP& m): m_map(m) {} + + virtual ~FunctorMapThreaded() {} + + /** + * @return a pointer on a copy of the object. + */ + virtual FunctorMapThreaded* duplicate() const { return NULL;} + + /** + * insert your code here: + * @param d the dart on which apply functor + * @param threadID the id of thread currently running your code + */ + virtual void run(Dart d, unsigned int threadID) = 0; +}; + + +/** + * Functor class for parallel::foreach_attrib + * Overload run + * Overload duplicate if necessary (no sharing of functors) + */ +class FunctorAttribThreaded +{ +public: + virtual ~FunctorAttribThreaded() {} + + /** + * @return a pointer on a copy of the object. + */ + virtual FunctorAttribThreaded* duplicate() const { return NULL;} + + /** + * insert your code here: + * @param d the dart on which apply functor + * @param threadID the id of thread currently running your code + */ + virtual void run(unsigned int i, unsigned int threadID) = 0; +}; + + } //namespace CGoGN #endif diff --git a/include/Topology/generic/genericmap.h b/include/Topology/generic/genericmap.h index 2310f5dcd0a8143e6d0bee07c412a37198d38703..619c499349f65a3db6d7a7b8e50b8a4f94aafb72 100644 --- a/include/Topology/generic/genericmap.h +++ b/include/Topology/generic/genericmap.h @@ -33,6 +33,8 @@ #include #include #include +#include + #include "Container/attributeContainer.h" @@ -83,6 +85,8 @@ protected: static std::map* m_attributes_registry_map ; + static int m_nbInstances; + /** * Direct access to the Dart attributes that store the orbits embeddings * (only initialized when necessary) @@ -110,9 +114,13 @@ protected: /** * Store links to created AttributeHandlers, DartMarkers and CellMarkers */ - std::multimap attributeHandlers ; - std::vector dartMarkers ; - std::vector cellMarkers ; + std::multimap attributeHandlers ; // TODO think of MT (AttributeHandler creation & release are not thread safe! + boost::mutex attributeHandlersMutex; + + std::vector dartMarkers[NB_THREAD] ; + std::vector cellMarkers[NB_THREAD] ; + + /** * is map a multiresolution map diff --git a/include/Topology/generic/traversor3.h b/include/Topology/generic/traversor3.h index dad38e69b0b7a0d041dd2f9ea09a90cb7e6f8a93..435eaeaed56b2d47e8937786981d3262f1fda53e 100644 --- a/include/Topology/generic/traversor3.h +++ b/include/Topology/generic/traversor3.h @@ -21,14 +21,15 @@ * Contact information: cgogn@unistra.fr * * * *******************************************************************************/ -#include "Topology/generic/traversorGen.h" #ifndef __TRAVERSOR3_H__ #define __TRAVERSOR3_H__ -#include "Topology/generic/dart.h" #include "Topology/generic/traversorCell.h" - +#include "Topology/generic/traversorGen.h" +#include "Topology/generic/traversorDoO.h" +#include "Topology/generic/dart.h" +#include "Topology/generic/cellmarker.h" namespace CGoGN { diff --git a/include/Topology/generic/traversorCell.h b/include/Topology/generic/traversorCell.h index 1de7f2aa353c6d425036a699f5c01a5c94c3c11a..7f5127a213c20d4849eeee09e42a3030c5e9bcc8 100644 --- a/include/Topology/generic/traversorCell.h +++ b/include/Topology/generic/traversorCell.h @@ -22,14 +22,13 @@ * * *******************************************************************************/ -#include "Topology/generic/traversorGen.h" - #ifndef __TRAVERSOR_CELL_H__ #define __TRAVERSOR_CELL_H__ #include "Topology/generic/dart.h" #include "Topology/generic/dartmarker.h" #include "Topology/generic/cellmarker.h" +#include "Topology/generic/traversorGen.h" namespace CGoGN { @@ -98,24 +97,6 @@ public: {} }; - -template -class TraversorDartsOfOrbit : public Traversor -{ -private: - std::vector::iterator m_current ; - std::vector m_vd ; - -public: - TraversorDartsOfOrbit(MAP& map, Dart d, unsigned int thread = 0) ; - - Dart begin() ; - - Dart end() ; - - Dart next() ; -} ; - } // namespace CGoGN #include "Topology/generic/traversorCell.hpp" diff --git a/include/Topology/generic/traversorCell.hpp b/include/Topology/generic/traversorCell.hpp index a012d73625c2aa0edb58d46799b6d7bc0b1bfae2..449ab25eaa54920ae91007c8c5da057578443365 100644 --- a/include/Topology/generic/traversorCell.hpp +++ b/include/Topology/generic/traversorCell.hpp @@ -153,35 +153,35 @@ void TraversorCell::skip(Dart d) cmark->mark(d) ; } - -template -TraversorDartsOfOrbit::TraversorDartsOfOrbit(MAP& map, Dart d, unsigned int thread) -{ - m_vd.reserve(16); - FunctorStoreNotBoundary fs(map, m_vd); - map.template foreach_dart_of_orbit(d, fs, thread); - m_vd.push_back(NIL); -} - -template -Dart TraversorDartsOfOrbit::begin() -{ - m_current = m_vd.begin(); - return *m_current; -} - -template -Dart TraversorDartsOfOrbit::end() -{ - return NIL; -} - -template -Dart TraversorDartsOfOrbit::next() -{ - if (*m_current != NIL) - m_current++; - return *m_current; -} +// +//template +//TraversorDartsOfOrbit::TraversorDartsOfOrbit(MAP& map, Dart d, unsigned int thread) +//{ +// m_vd.reserve(16); +// FunctorStoreNotBoundary fs(map, m_vd); +// map.template foreach_dart_of_orbit(d, fs, thread); +// m_vd.push_back(NIL); +//} +// +//template +//Dart TraversorDartsOfOrbit::begin() +//{ +// m_current = m_vd.begin(); +// return *m_current; +//} +// +//template +//Dart TraversorDartsOfOrbit::end() +//{ +// return NIL; +//} +// +//template +//Dart TraversorDartsOfOrbit::next() +//{ +// if (*m_current != NIL) +// m_current++; +// return *m_current; +//} } // namespace CGoGN diff --git a/include/Topology/generic/traversorDoO.h b/include/Topology/generic/traversorDoO.h new file mode 100644 index 0000000000000000000000000000000000000000..87c77e259e4a1a08f47a26fe592d21ac84d0de0b --- /dev/null +++ b/include/Topology/generic/traversorDoO.h @@ -0,0 +1,57 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, 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. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __TRAVERSOR_DOO_H__ +#define __TRAVERSOR_DOO_H__ + +#include "Topology/generic/traversorGen.h" + +#include "Topology/generic/dart.h" + + +namespace CGoGN +{ + +template +class TraversorDartsOfOrbit : public Traversor +{ +private: + std::vector::iterator m_current ; + std::vector m_vd ; + +public: + TraversorDartsOfOrbit(MAP& map, Dart d, unsigned int thread = 0) ; + + Dart begin() ; + + Dart end() ; + + Dart next() ; +} ; + +} // namespace CGoGN + +#include "Topology/generic/traversorDoO.hpp" + +#endif diff --git a/include/Topology/generic/traversorDoO.hpp b/include/Topology/generic/traversorDoO.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cdd6c965852e78d9e839b4b08c355d844ef2e6e5 --- /dev/null +++ b/include/Topology/generic/traversorDoO.hpp @@ -0,0 +1,63 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, 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. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include "Topology/generic/genericmap.h" +#include "Topology/generic/functor.h" + + +namespace CGoGN +{ + + +template +TraversorDartsOfOrbit::TraversorDartsOfOrbit(MAP& map, Dart d, unsigned int thread) +{ + m_vd.reserve(16); + FunctorStoreNotBoundary fs(map, m_vd); + map.template foreach_dart_of_orbit(d, fs, thread); + m_vd.push_back(NIL); +} + +template +Dart TraversorDartsOfOrbit::begin() +{ + m_current = m_vd.begin(); + return *m_current; +} + +template +Dart TraversorDartsOfOrbit::end() +{ + return NIL; +} + +template +Dart TraversorDartsOfOrbit::next() +{ + if (*m_current != NIL) + m_current++; + return *m_current; +} + +} // namespace CGoGN diff --git a/include/Topology/generic/traversorFactory.h b/include/Topology/generic/traversorFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..b4137245e0a36fffe3f75a135375da430bc56aa4 --- /dev/null +++ b/include/Topology/generic/traversorFactory.h @@ -0,0 +1,86 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, 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. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __TRAVERSORFACTORY_H__ +#define __TRAVERSORGEN_H__ + +#include "Topology/generic/traversorGen.h" + +namespace CGoGN +{ + +template +class TraversorFactory +{ +public: + + /** + * Factory of incident traversors creation + * @param map the map in which we work + * @param dart the initial dart of traversal + * @param dim the dimension of traversal (2 or 3) + * @param orbX incident from cell + * @param orbY incident to cell + * @return a ptr on Generic Traversor + */ + static Traversor* createIncident(MAP& map, Dart dart, unsigned int dim, unsigned int orbX, unsigned int orbY); + + /** + * Factory of adjacent traversors creation + * @param map the map in which we work + * @param dart the initial dart of traversal + * @param dim the dimension of traversal (2 or 3) + * @param orbX incident from cell + * @param orbY incident to cell + * @return a ptr on Generic Traversor + */ + static Traversor* createAdjacent(MAP& map, Dart dart, unsigned int dim, unsigned int orbX, unsigned int orbY); + + /** + * Factory of darts of orbit traversors creation + * @param map the map in which we work + * @param dart the initial dart of traversal + * @param orb the orbit + * @return a ptr on Generic Traversor + */ + static Traversor* createDartsOfOrbits(MAP& map, Dart dart, unsigned int orb); + + /** + * Factory of incident traversors creation + * @param map the map in which we work + * @param good the selector (default value allDarts) + * @param forceDartMarker (default value false) + * @param thread (default value 0) + * @return a ptr on Generic Traversor + */ + static Traversor* createCell(MAP& map, unsigned int orb, const FunctorSelect& good = allDarts, bool forceDartMarker = false, unsigned int thread = 0); +}; + +} // namespace CGoGN + + +#include "Topology/generic/traversorFactory.hpp" + +#endif + diff --git a/include/Topology/generic/traversorGen.hpp b/include/Topology/generic/traversorFactory.hpp similarity index 93% rename from include/Topology/generic/traversorGen.hpp rename to include/Topology/generic/traversorFactory.hpp index 05444095efe7d0b1b87c4a4d48ee57399dc962da..04bd8e1a3c9de7d7d51411175f52df3e1423357d 100644 --- a/include/Topology/generic/traversorGen.hpp +++ b/include/Topology/generic/traversorFactory.hpp @@ -25,12 +25,13 @@ #include "Topology/generic/traversor2.h" #include "Topology/generic/traversor3.h" #include "Topology/generic/traversorCell.h" +#include "Topology/generic/traversorDoO.h" namespace CGoGN { template -Traversor* Traversor::createIncident(MAP& map, Dart dart, unsigned int dim, unsigned int orbX, unsigned int orbY) +Traversor* TraversorFactory::createIncident(MAP& map, Dart dart, unsigned int dim, unsigned int orbX, unsigned int orbY) { int code = 0x100*dim + 0x10*(orbX-VERTEX) + orbY-VERTEX; @@ -114,7 +115,7 @@ Traversor* Traversor::createIncident(MAP& map, Dart dart, unsigned int template -Traversor* Traversor::createAdjacent(MAP& map, Dart dart, unsigned int dim, unsigned int orbX, unsigned int orbY) +Traversor* TraversorFactory::createAdjacent(MAP& map, Dart dart, unsigned int dim, unsigned int orbX, unsigned int orbY) { int code = 0x100*dim + 0x10*(orbX-VERTEX) + orbY-VERTEX; @@ -191,16 +192,14 @@ Traversor* Traversor::createAdjacent(MAP& map, Dart dart, unsigned int default: return NULL; break; - } - return NULL; } template -Traversor* Traversor::createCell(MAP& map, unsigned int orb, const FunctorSelect& good, bool forceDartMarker, unsigned int thread) +Traversor* TraversorFactory::createCell(MAP& map, unsigned int orb, const FunctorSelect& good, bool forceDartMarker, unsigned int thread) { switch(orb) { @@ -241,7 +240,7 @@ Traversor* Traversor::createCell(MAP& map, unsigned int orb, const Fun } template -Traversor* Traversor::createDartsOfOrbits(MAP& map, Dart dart, unsigned int orb) +Traversor* TraversorFactory::createDartsOfOrbits(MAP& map, Dart dart, unsigned int orb) { switch(orb) { @@ -282,10 +281,6 @@ Traversor* Traversor::createDartsOfOrbits(MAP& map, Dart dart, unsigne } - - - - } diff --git a/include/Topology/generic/traversorGen.h b/include/Topology/generic/traversorGen.h index ee0c819699986d54f12673a7bdcf5494da178b26..bf4e4fd4e0903c187638cfddae212b7647f1f7bf 100644 --- a/include/Topology/generic/traversorGen.h +++ b/include/Topology/generic/traversorGen.h @@ -84,7 +84,7 @@ public: } // namespace CGoGN -#include "Topology/generic/traversorGen.hpp" +//#include "Topology/generic/traversorGen.hpp" #endif diff --git a/include/Utils/clippingPresets.h b/include/Utils/clippingPresets.h index 768d1c40871e9942ce6c7d5ea3dd5d7ac4e35898..6ca3c79593dc443a7bcc053ba2de20e6f5030a88 100644 --- a/include/Utils/clippingPresets.h +++ b/include/Utils/clippingPresets.h @@ -48,6 +48,8 @@ class ClippingPreset public : + virtual ~ClippingPreset() {} + /// public static constructor static ClippingPreset* CreateEmptyPreset(); @@ -92,7 +94,6 @@ protected : /// protected constructor (used by public static constructors or child class) ClippingPreset(); - /*********************************************** * * Preset settings diff --git a/include/Utils/pointSprite.frag b/include/Utils/pointSprite.frag index 3fb54e2776633a21bd8e0bc3a8018d60a91029bc..3d026d648dd6286fd24a2853caaa417a54d68814 100644 --- a/include/Utils/pointSprite.frag +++ b/include/Utils/pointSprite.frag @@ -1,7 +1,15 @@ // PointSprite::fragmentShaderText + uniform sampler2D SpriteTexture; uniform float size; -uniform vec3 color; + +#ifdef WITH_COLOR_PER_VERTEX + VARYING_FRAG vec3 colorsprite; +#else + uniform vec3 colorsprite; +#endif + + VARYING_FRAG vec2 texCoord; VARYING_FRAG vec2 positionFragIn; VARYING_FRAG vec4 mvpFragIn; @@ -14,5 +22,5 @@ void main(void) float z = size * sqrt(1.0-dot(v,v)); vec2 zfrag = positionFragIn + vec2(z,0.0); gl_FragDepth = 0.5 + 0.5 * dot(zfrag, mvpFragIn.xy) / dot(zfrag, mvpFragIn.zw); - gl_FragColor = vec4(color,0.0)*lum; -} \ No newline at end of file + gl_FragColor = vec4(colorsprite,0.0)*lum; +} diff --git a/include/Utils/pointSprite.geom b/include/Utils/pointSprite.geom index 7bb849d9f592b9d8a23f96304796f14c938329d1..e21aa3764ee6c4f8c8b9400d25a2d9fdecae023b 100644 --- a/include/Utils/pointSprite.geom +++ b/include/Utils/pointSprite.geom @@ -6,6 +6,12 @@ uniform mat4 ProjectionMatrix; VARYING_OUT vec2 texCoord; VARYING_OUT vec2 positionFragIn; VARYING_OUT vec4 mvpFragIn; + +#ifdef WITH_COLOR_PER_VERTEX + VARYING_IN vec3 color[1]; + VARYING_OUT vec3 colorsprite; +#endif + void main() { vec4 posCenter = ModelViewMatrix * POSITION_IN(0); @@ -16,6 +22,10 @@ void main() mvpFragIn.z = ProjectionMatrix[2][3]; mvpFragIn.w = ProjectionMatrix[3][3]; texCoord = vec2(0.0,1.0); + +#ifdef WITH_COLOR_PER_VERTEX + colorsprite = color[0]; +#endif gl_Position = ProjectionMatrix * pos; EmitVertex(); pos = posCenter + vec4(-size, -size, 0.0, 0.0); diff --git a/include/Utils/pointSprite.h b/include/Utils/pointSprite.h index 4aaca2faa80fe6102ac6b5578118116f162e0640..b35411516032b53e65ead04858d283675b7eb076 100644 --- a/include/Utils/pointSprite.h +++ b/include/Utils/pointSprite.h @@ -63,8 +63,11 @@ protected: public: /** * init shaders, texture and variables + * @param withColorPerVertex if true use setAttributeColor for per vertex color, else use predraw(color) for global color + * @param radius of sphere */ - PointSprite(float radius = 1.0f); + + PointSprite(bool withColorPerVertex=false, float radius=1.0f); /** * clean shaders, texture and variables @@ -73,9 +76,15 @@ public: /** * call once before sending points to gpu + * @param color set global color of sprites */ void predraw(const Geom::Vec3f& color); + /** + * call once before sending points to gpu + */ + void predraw(); + /** * call once after sending points to gpu */ @@ -91,10 +100,14 @@ public: * set position attribute */ unsigned int setAttributePosition(VBO* vbo); + + /** + * set color attribute + */ + unsigned int setAttributeColor(VBO* vbo); }; } // namespace Utils } // namespace CGoGN - #endif diff --git a/include/Utils/pointSprite.vert b/include/Utils/pointSprite.vert index 2e3eff771df1bd4f1c68920e3a533e89b2ea2ba5..d2500cff693eaf734042d21d4a3b4a9f1404050a 100644 --- a/include/Utils/pointSprite.vert +++ b/include/Utils/pointSprite.vert @@ -1,6 +1,15 @@ // PointSprite::vertexShaderText + ATTRIBUTE vec3 VertexPosition; +#ifdef WITH_COLOR_PER_VERTEX + ATTRIBUTE vec3 VertexColor; + VARYING_VERT vec3 color; +#endif + void main () { gl_Position = vec4(VertexPosition,1.0); +#ifdef WITH_COLOR_PER_VERTEX + color = VertexColor; //VertexColor; +#endif } diff --git a/include/Utils/textures.h b/include/Utils/textures.h index d1fe4db1898ee827b31e5e86e8682670ea59a1e4..638c1c3a0cd11680ba09e51a0eaa5fd81305bf0b 100644 --- a/include/Utils/textures.h +++ b/include/Utils/textures.h @@ -45,6 +45,7 @@ namespace Utils class GTexture { public: + virtual ~GTexture() {} virtual void bind() {} }; diff --git a/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp b/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp index 9ed2d422a01bfd69d191e88f53ee633fe814a8aa..39722019bc19cc7abf005bd33602a26edb4d4ccc 100644 --- a/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp +++ b/src/Algo/ImplicitHierarchicalMesh/ihm3.cpp @@ -23,6 +23,7 @@ *******************************************************************************/ #include "Algo/ImplicitHierarchicalMesh/ihm3.h" +#include "Topology/generic/traversor3.h" #include #include @@ -52,6 +53,20 @@ ImplicitHierarchicalMap3::~ImplicitHierarchicalMap3() removeAttribute(m_dartLevel) ; } +void ImplicitHierarchicalMap3::clear(bool removeAttrib) +{ + Map3::clear(removeAttrib) ; + if (removeAttrib) + { + m_dartLevel = Map3::addAttribute("dartLevel") ; + m_faceId = Map3::addAttribute("faceId") ; + m_edgeId = Map3::addAttribute("edgeId") ; + + for(unsigned int i = 0; i < NB_ORBITS; ++i) + m_nextLevelCell[i] = NULL ; + } +} + void ImplicitHierarchicalMap3::init() { initEdgeId() ; diff --git a/src/Algo/Parallel/parallel_foreach.cpp b/src/Algo/Parallel/parallel_foreach.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4cc5fef859baedf3b9067fd29fdddb87424347c --- /dev/null +++ b/src/Algo/Parallel/parallel_foreach.cpp @@ -0,0 +1,140 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, 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. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ +#include "Topology/generic/genericmap.h" +#include "Algo/Parallel/parallel_foreach.h" + + +namespace CGoGN +{ + +namespace Algo +{ + +namespace Parallel +{ + +void setNbCore(unsigned int nb) +{ + NBCORES = nb; +} + + + +void foreach_attrib(AttributeContainer& attr_cont, FunctorAttribThreaded& func, unsigned int nbth) +{ + if (nbth == 0) + nbth = optimalNbThreads(); + + std::vector funcs; + funcs.reserve(nbth); + + FunctorAttribThreaded* ptr = func.duplicate(); + bool shared = (ptr == NULL); + + if (shared) + { + for (unsigned int i = 0; i < nbth; ++i) + funcs.push_back(&func); + } + else + { + funcs.push_back(ptr); + for (unsigned int i = 1; i < nbth; ++i) + funcs.push_back(func.duplicate()); + } + + foreach_attrib(attr_cont,funcs); + + if (!shared) + for (unsigned int i = 0; i < nbth; ++i) + delete funcs[i]; + +} + +void foreach_attrib(AttributeContainer& attr_cont, std::vector funcs) +{ + unsigned int nbth = funcs.size(); + + std::vector* vid = new std::vector[2*nbth]; + boost::thread** threads = new boost::thread*[nbth]; + + for (unsigned int i = 0; i < 2*nbth; ++i) + vid[i].reserve(SIZE_BUFFER_THREAD); + + // fill each vid buffers with 4096 id + unsigned int id = attr_cont.begin(); + unsigned int nb = 0; + unsigned int nbm = nbth*SIZE_BUFFER_THREAD; + while ((id != attr_cont.end()) && (nb < nbm)) + { + vid[nb%nbth].push_back(id); + nb++; + attr_cont.next(id); + } + + + boost::barrier sync1(nbth+1); + boost::barrier sync2(nbth+1); + bool finished=false; + // lauch threads + for (unsigned int i = 0; i < nbth; ++i) + threads[i] = new boost::thread(ThreadFunctionAttrib(funcs[i], vid[i],sync1,sync2, finished,1+i)); + + while (id != attr_cont.end()) + { + for (unsigned int i = nbth; i < 2*nbth; ++i) + vid[i].clear(); + + unsigned int nb = 0; + while ((id != attr_cont.end()) && (nb < nbm)) + { + vid[nbth + nb%nbth].push_back(id); + nb++; + attr_cont.next(id); + } + + sync1.wait(); + for (unsigned int i = 0; i < nbth; ++i) + vid[i].swap(vid[nbth+i]); + sync2.wait(); + } + + sync1.wait(); + finished = true; + sync2.wait(); + + //wait for all theads to be finished + for (unsigned int i = 0; i < nbth; ++i) + { + threads[i]->join(); + delete threads[i]; + } + delete[] threads; + delete[] vid; +} + + +} +} // end namespaces +} diff --git a/src/Container/attributeContainer.cpp b/src/Container/attributeContainer.cpp index 6cae3bff34519b01bc1fa4de574d86186c2dada4..b8b7a590ef6c0c0f6305a62da4f117d4fab9e569 100644 --- a/src/Container/attributeContainer.cpp +++ b/src/Container/attributeContainer.cpp @@ -48,6 +48,18 @@ AttributeContainer::AttributeContainer() : AttributeContainer::~AttributeContainer() { + for (unsigned int index = 0; index < m_tableAttribs.size(); ++index) + { + if (m_tableAttribs[index] != NULL) + delete m_tableAttribs[index]; + } + + for (unsigned int index = 0; index < m_holesBlocks.size(); ++index) + { + if (m_holesBlocks[index] != NULL) + delete m_holesBlocks[index]; + } + } /************************************** @@ -157,14 +169,14 @@ void AttributeContainer::clear(bool removeAttrib) m_size = 0; m_maxSize = 0; - std::vector bf; - std::vector bwf; - - // raz des cases libres + // raz des cases libres for (std::vector::iterator it = m_holesBlocks.begin(); it != m_holesBlocks.end(); ++it) delete (*it); + std::vector bf; m_holesBlocks.swap(bf); + + std::vector bwf; m_tableBlocksWithFree.swap(bwf); // detruit les données @@ -181,13 +193,17 @@ void AttributeContainer::clear(bool removeAttrib) m_nbAttributes = 0; // detruit tous les attributs - std::vector amg; for (std::vector::iterator it = m_tableAttribs.begin(); it != m_tableAttribs.end(); ++it) { if ((*it) != NULL) delete (*it); } + + std::vector amg; m_tableAttribs.swap(amg); + + std::vector fi; + m_freeIndices.swap(fi); } } diff --git a/src/Topology/generic/attribmap.cpp b/src/Topology/generic/attribmap.cpp index 85332e5c95a2d4fa58f4a09f1e083750eca9f90e..860bd1802bf639afadc781c9e31ab8f7f1f4f8e9 100644 --- a/src/Topology/generic/attribmap.cpp +++ b/src/Topology/generic/attribmap.cpp @@ -43,16 +43,22 @@ void AttribMap::init() } } - for(unsigned int i = 0; i < cellMarkers.size(); ++i) + for (unsigned int j=0; jupdateMarkVector(m_markTables[cm->getCell()][cm->getThread()]) ; - } + std::vector& cmg = cellMarkers[j]; - for(unsigned int i = 0; i < dartMarkers.size(); ++i) - { - DartMarkerGen* cm = dartMarkers[i] ; - cm->updateMarkVector(m_markTables[DART][cm->getThread()]) ; + for(unsigned int i = 0; i < cmg.size(); ++i) + { + CellMarkerGen* cm = cmg[i] ; + cm->updateMarkVector(m_markTables[cm->getCell()][cm->getThread()]) ; + } + + std::vector& dmg = dartMarkers[j]; + for(unsigned int i = 0; i < dmg.size(); ++i) + { + DartMarkerGen* cm = dmg[i] ; + cm->updateMarkVector(m_markTables[DART][cm->getThread()]) ; + } } } diff --git a/src/Topology/generic/genericmap.cpp b/src/Topology/generic/genericmap.cpp index 20a4fcfc47e662981d30be4d9cbfdb6b5a1ae369..7ec8a5b3b236fe14881fa09ab1916a103fd5e054 100644 --- a/src/Topology/generic/genericmap.cpp +++ b/src/Topology/generic/genericmap.cpp @@ -34,12 +34,15 @@ namespace CGoGN { std::map* GenericMap::m_attributes_registry_map = NULL ; +int GenericMap::m_nbInstances = 0; GenericMap::GenericMap() : m_nbThreads(1) { if(m_attributes_registry_map == NULL) m_attributes_registry_map = new std::map ; + + m_nbInstances++; // register all known types registerAttribute("Dart"); registerAttribute("Mark"); @@ -81,8 +84,11 @@ GenericMap::GenericMap() : m_nbThreads(1) } } - dartMarkers.reserve(16) ; - cellMarkers.reserve(16) ; + for (unsigned int i=0; i::iterator it = attributeHandlers.begin(); it != attributeHandlers.end(); ++it) (*it).second->setInvalid() ; attributeHandlers.clear() ; - for(std::vector::iterator it = dartMarkers.begin(); it != dartMarkers.end(); ++it) - (*it)->setReleaseOnDestruct(false) ; - dartMarkers.clear() ; + for (unsigned int i=0; i::iterator it = dartMarkers[i].begin(); it != dartMarkers[i].end(); ++it) + (*it)->setReleaseOnDestruct(false) ; + dartMarkers[i].clear() ; - for(std::vector::iterator it = cellMarkers.begin(); it != cellMarkers.end(); ++it) - (*it)->setReleaseOnDestruct(false) ; - cellMarkers.clear() ; + for(std::vector::iterator it = cellMarkers[i].begin(); it != cellMarkers[i].end(); ++it) + (*it)->setReleaseOnDestruct(false) ; + cellMarkers[i].clear() ; + } - if(m_attributes_registry_map) + // clean type registry if necessary + m_nbInstances--; + if (m_nbInstances<=0) { + for (std::map::iterator it = m_attributes_registry_map->begin(); it != m_attributes_registry_map->end(); ++it) + delete it->second; + delete m_attributes_registry_map; m_attributes_registry_map = NULL; } @@ -130,6 +145,7 @@ void GenericMap::clear(bool removeAttrib) { m_attribs[i].clear(true) ; m_embeddings[i] = NULL ; + m_quickTraversal[i] = NULL; } for(std::multimap::iterator it = attributeHandlers.begin(); it != attributeHandlers.end(); ++it) (*it).second->setInvalid() ; diff --git a/src/Utils/GLSLShader.cpp b/src/Utils/GLSLShader.cpp index 3955297b08a400e3884d9c7345cc8eba59c67b7a..4ace496f137e05eb62a7497be440ead18f3cd9b8 100644 --- a/src/Utils/GLSLShader.cpp +++ b/src/Utils/GLSLShader.cpp @@ -207,6 +207,7 @@ bool GLSLShader::loadVertexShader( const std::string& filename ) if (m_vertex_shader_source) delete [] m_vertex_shader_source; + m_vertex_shader_source = NULL; m_vertex_shader_source = loadSourceFile( filename ); @@ -230,6 +231,7 @@ bool GLSLShader::loadFragmentShader(const std::string& filename ) if (m_fragment_shader_source) delete [] m_fragment_shader_source; + m_fragment_shader_source = NULL; m_fragment_shader_source = loadSourceFile( filename ); @@ -586,6 +588,13 @@ GLSLShader::~GLSLShader() glDeleteObjectARB( m_program_object ); } + if (m_vertex_shader_source != NULL) + delete[] m_vertex_shader_source; + if (m_fragment_shader_source != NULL) + delete[] m_fragment_shader_source; + if (m_geom_shader_source != NULL) + delete[] m_geom_shader_source; + // m_registeredShaders.erase(this); } @@ -702,6 +711,7 @@ bool GLSLShader::loadShadersFromMemory(const char* vs, const char* fs) { if (m_vertex_shader_source) delete [] m_vertex_shader_source; + m_vertex_shader_source = NULL; unsigned int sz = strlen(vs); m_vertex_shader_source = new char[sz+1]; @@ -730,9 +740,11 @@ bool GLSLShader::loadShadersFromMemory(const char* vs, const char* fs, const cha { if (m_vertex_shader_source) delete [] m_vertex_shader_source; + m_vertex_shader_source = NULL; unsigned int sz = strlen(vs); m_vertex_shader_source = new char[sz+1]; + strcpy(m_vertex_shader_source,vs); if (m_fragment_shader_source) @@ -771,9 +783,11 @@ bool GLSLShader::reloadVertexShaderFromMemory(const char* vs) { if (m_vertex_shader_source) delete [] m_vertex_shader_source; + m_vertex_shader_source = NULL; unsigned int sz = strlen(vs); m_vertex_shader_source = new char[sz+1]; + strcpy(m_vertex_shader_source,vs); return true; diff --git a/src/Utils/Qt/qtSimple.cpp b/src/Utils/Qt/qtSimple.cpp index 29454c8c04e0e77b6b41948f032ac8fb5338b4c5..6ee40cca1e4b48fa0ac4153b9776058b5bb2b152 100644 --- a/src/Utils/Qt/qtSimple.cpp +++ b/src/Utils/Qt/qtSimple.cpp @@ -99,7 +99,7 @@ SimpleQT::SimpleQT() : m_textConsole = new QTextEdit(); m_textConsole->setLineWrapMode(QTextEdit::NoWrap); m_textConsole->setTabStopWidth(20); - m_textConsole->setReadOnly(true); +// m_textConsole->setReadOnly(true); m_dockConsole->setWidget(m_textConsole); diff --git a/src/Utils/Qt/qtcolorschooser.cpp b/src/Utils/Qt/qtcolorschooser.cpp index dd63f9b32f7b72f3e64111ac4cc8666b0f5c92c2..307646e22ac9a51db61476cb1cd079290affb00a 100644 --- a/src/Utils/Qt/qtcolorschooser.cpp +++ b/src/Utils/Qt/qtcolorschooser.cpp @@ -36,7 +36,7 @@ namespace QT ColorsChooser::ColorsChooser(SimpleQT *interf): - QtPopUp(false),m_interf(interf),m_current(0) + QtPopUp(NULL,false),m_interf(interf),m_current(0) { m_list = new QListWidget(); m_diag = new QColorDialog(); diff --git a/src/Utils/Qt/qtgl.cpp b/src/Utils/Qt/qtgl.cpp index e6805a4a2f9117d5fb1713126ffd5187d29b52c4..dc267d79d566d2a77fe751a4e9380b1b64d178eb 100644 --- a/src/Utils/Qt/qtgl.cpp +++ b/src/Utils/Qt/qtgl.cpp @@ -329,6 +329,7 @@ void GLWidget::keyPressEvent(QKeyEvent* event) { close(); m_cbs->close(); + return; } m_state_modifier = event->modifiers(); diff --git a/src/Utils/pointSprite.cpp b/src/Utils/pointSprite.cpp index efa9d5b48cc274a782099124adc75559e643e194..02ff0a542357912dafd118cb750396bdf0669b1c 100644 --- a/src/Utils/pointSprite.cpp +++ b/src/Utils/pointSprite.cpp @@ -40,85 +40,30 @@ GLuint PointSprite::m_uniform_texture = 0; unsigned char* PointSprite::m_ptrSphere = NULL; -//std::string PointSprite::vertexShaderText = -//"ATTRIBUTE vec3 VertexPosition;\n" -//"void main ()\n" -//"{\n" -//" gl_Position = vec4(VertexPosition,1.0);\n" -//"}"; - - -//std::string PointSprite::geometryShaderText = -//"uniform float size;\n" -//"uniform mat4 ModelViewMatrix;\n" -//"uniform mat4 ProjectionMatrix;\n" -//"VARYING_OUT vec2 texCoord;\n" -//"VARYING_OUT vec2 positionFragIn;\n" -//"VARYING_OUT vec4 mvpFragIn;\n" -//"void main()\n" -//"{\n" -//" vec4 posCenter = ModelViewMatrix * POSITION_IN(0);\n" -//" vec4 pos = posCenter + vec4(-size, size, 0.0, 0.0);\n" -//" positionFragIn = posCenter.zw;\n" -//" mvpFragIn.x = ProjectionMatrix[2][2];\n" -//" mvpFragIn.y = ProjectionMatrix[3][2];\n" -//" mvpFragIn.z = ProjectionMatrix[2][3];\n" -//" mvpFragIn.w = ProjectionMatrix[3][3];\n" -//" texCoord = vec2(0.0,1.0);\n" -//" gl_Position = ProjectionMatrix * pos;\n" -//" EmitVertex();\n" -//" pos = posCenter + vec4(-size, -size, 0.0, 0.0);\n" -//" texCoord = vec2(0.0,0.0);\n" -//" gl_Position = ProjectionMatrix * pos;\n" -//" EmitVertex();\n" -//" pos = posCenter + vec4( size, size, 0.0, 0.0);\n" -//" texCoord = vec2(1.0,1.0);\n" -//" gl_Position = ProjectionMatrix * pos;\n" -//" EmitVertex();\n" -//" pos = posCenter + vec4( size,-size, 0.0, 0.0);\n" -//" texCoord = vec2(1.0,0.0);\n" -//" gl_Position = ProjectionMatrix * pos;\n" -//" EmitVertex();\n" -//" EndPrimitive();\n" -//"}"; - - -//std::string PointSprite::fragmentShaderText = -//"uniform sampler2D SpriteTexture;\n" -//"uniform float size;\n" -//"uniform vec3 color;\n" -//"VARYING_FRAG vec2 texCoord;\n" -//"VARYING_FRAG vec2 positionFragIn;\n" -//"VARYING_FRAG vec4 mvpFragIn;\n" -//"void main(void)\n" -//"{\n" -//" float lum = texture2D(SpriteTexture, texCoord).s;\n" -//" if (lum==0.0)\n" -//" discard;\n" -//" vec2 v = texCoord-vec2(0.5,0.5);\n" -//" float z = size * sqrt(1.0-dot(v,v));\n" -//" vec2 zfrag = positionFragIn + vec2(z,0.0);\n" -//" gl_FragDepth = 0.5 + 0.5 * dot(zfrag, mvpFragIn.xy) / dot(zfrag, mvpFragIn.zw);\n" -//" gl_FragColor = vec4(color,0.0)*lum;\n" -//"}"; - - -PointSprite::PointSprite(float radius) +PointSprite::PointSprite(bool withColorPervertex, float radius) { + std::string defineColor("#define WITH_COLOR_PER_VERTEX 1\n"); + std::string glxvert(*GLSLShader::DEFINES_GL); + if (withColorPervertex) + glxvert.append(defineColor); glxvert.append(vertexShaderText); std::string glxgeom = GLSLShader::defines_Geom("points","triangle_strip",4); + if (withColorPervertex) + glxgeom.append(defineColor); glxgeom.append(geometryShaderText); std::string glxfrag(*GLSLShader::DEFINES_GL); + if (withColorPervertex) + glxfrag.append(defineColor); glxfrag.append(fragmentShaderText); loadShadersFromMemory(glxvert.c_str(), glxfrag.c_str(), glxgeom.c_str(), GL_POINTS, GL_TRIANGLE_STRIP,4); bind(); m_uniform_size = glGetUniformLocation(program_handler(),"size"); - m_uniform_color = glGetUniformLocation(program_handler(),"color"); + m_uniform_color = glGetUniformLocation(program_handler(),"colorsprite"); glUniform1f(m_uniform_size, radius); unbind(); @@ -149,6 +94,11 @@ unsigned int PointSprite::setAttributePosition(VBO* vbo) return bindVA_VBO("VertexPosition", vbo); } +unsigned int PointSprite::setAttributeColor(VBO* vbo) +{ + return bindVA_VBO("VertexColor", vbo); +} + void PointSprite::predraw(const Geom::Vec3f& color) { bind(); @@ -159,6 +109,15 @@ void PointSprite::predraw(const Geom::Vec3f& color) glEnable(GL_TEXTURE_2D); } +void PointSprite::predraw() +{ + bind(); + glUniform1i(m_uniform_texture, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_idTexture); + glEnable(GL_TEXTURE_2D); +} + void PointSprite::postdraw() { glDisable(GL_TEXTURE_2D); diff --git a/src/Utils/svg.cpp b/src/Utils/svg.cpp index d3ebe4b40da933c7b6a5f20027c5efbd60b61509..aea98aff6f0245a936c667fdf726f35e451a589b 100644 --- a/src/Utils/svg.cpp +++ b/src/Utils/svg.cpp @@ -498,14 +498,14 @@ void SVGOut::endPoints() void SVGOut::addPoint(const Geom::Vec3f& P) { glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport); - glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); +// glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); m_current->addVertex(Geom::Vec3f(float(Q[0]),float(m_viewport[3])-float(Q[1]),float(Q[2]))); } void SVGOut::addPoint(const Geom::Vec3f& P, const Geom::Vec3f& C) { glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport); - glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); +// glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); m_current->addVertex(Geom::Vec3f(float(Q[0]),float(m_viewport[3])-float(Q[1]),float(Q[2])),C); } @@ -527,10 +527,10 @@ void SVGOut::endLines() void SVGOut::addLine(const Geom::Vec3f& P, const Geom::Vec3f& P2) { glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport); - glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); +// glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); glm::vec3 Q2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,m_proj,m_viewport); - glm::vec3 R2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,glm::mat4(1.0),m_viewport); +// glm::vec3 R2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,glm::mat4(1.0),m_viewport); m_current->addVertex(Geom::Vec3f(float(Q[0]),float(m_viewport[3])-float(Q[1]),float(Q[2]))); m_current->addVertex(Geom::Vec3f(float(Q2[0]),float(m_viewport[3])-float(Q2[1]),float(Q2[2]))); @@ -541,10 +541,10 @@ void SVGOut::addLine(const Geom::Vec3f& P, const Geom::Vec3f& P2) void SVGOut::addLine(const Geom::Vec3f& P, const Geom::Vec3f& P2, const Geom::Vec3f& C) { glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport); - glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); +// glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport); glm::vec3 Q2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,m_proj,m_viewport); - glm::vec3 R2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,glm::mat4(1.0),m_viewport); +// glm::vec3 R2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,glm::mat4(1.0),m_viewport); m_current->addVertex(Geom::Vec3f(float(Q[0]),float(m_viewport[3])-float(Q[1]),float(Q[2])),C); m_current->addVertex(Geom::Vec3f(float(Q2[0]),float(m_viewport[3])-float(Q2[1]),float(Q2[2])),C);