/** * @brief computeLengthEdges * Demonstrate usage of 2 attributes on 2 differents orbits. * @param map the map * @param pos attribute handler of position of vertices * @param len attribute handler of length of edges */ void computeLengthEdges(MAP& map,const VertexAttribute<VEC3, MAP>& pos, EdgeAttribute<float, MAP> len) { // warning c++11 lambda syntax foreach_cell<EDGE>(map,[&](Edge e) // for all edge e of map do { VEC3 P1 = pos[e.dart]; // access with dart because of access to VertexAttribute with an edge VEC3 P2 = pos[map.phi1(e)]; // phi1 return a dart so no problem (and e can auto-cast in dart) VEC3 V = P2 - P1; len[e] = V.norm(); }); }
int main(int argc, char **argv) { position = myMap.addAttribute<VEC3, VERTEX>("position"); Dart d0 = myMap.newFace(12); position[d0] = PFP::VEC3(0, 20, 0); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(10, 20, 0); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(10, 30, 0); Dart dx = myMap.phi1(d0); d0 = myMap.phi<11>(dx); position[d0] = PFP::VEC3(8, 27, 0); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(8, 22, 0); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(2, 22, 0); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(2, 27, 0); d0 = myMap.phi1(d0); myMap.sewFaces(d0,dx); position[d0] = PFP::VEC3(5, 27, 0); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(5, 30, 0); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(0, 30, 0); d0 = myMap.newFace(4); position[d0] = PFP::VEC3(-5, 14, -5); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(0, 18, -5); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(5, 14, -5); d0 = myMap.phi1(d0); position[d0] = PFP::VEC3(0, 20, -5); d0 = myMap.phi1(d0); Dart d1 = myMap.newFace(10); position[d1] = PFP::VEC3(0, 0, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(2, 4, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(4, 0, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(10, 0, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(4, 2, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(14, 6, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(6, 16, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(8, 8, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(4, 4, 0); d1 = myMap.phi1(d1); position[d1] = PFP::VEC3(0, 8, 0); Dart d2 = myMap.newFace(12); position[d2] = PFP::VEC3(0, -20, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(4, -20, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(8, -20, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(12, -20, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(12, -16, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(12, -12, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(12, -8, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(8, -8, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(4, -8, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(0, -8, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(0, -12, 0); d2 = myMap.phi1(d2); position[d2] = PFP::VEC3(0, -16, 0); d2 = myMap.phi1(d2); #define NB 32 //SPIRAL Dart d3 = myMap.newFace(NB*2); for (int i = 0; i<NB; ++i) { float z = 3.0f*float(rand()-RAND_MAX/2)/float(RAND_MAX); float alpha = (4.0f*6.283f / NB)*i; float radius = 1.2f*(NB-i); position[d3] = PFP::VEC3(radius*cos(alpha) - 2*NB+8, radius*sin(alpha), z); d3 = myMap.phi1(d3); } for (int i = NB-1; i>=0; --i) { float z = 3.0f*float(rand()-RAND_MAX/2)/float(RAND_MAX); float alpha = (4.0f*6.283f / NB)*i; float radius = (NB-i); position[d3] = PFP::VEC3(radius*cos(alpha) - 2*NB+8, radius*sin(alpha), z); d3 = myMap.phi1(d3); } //CIRCLE Dart d6 = myMap.newFace(NB); for (int i = 0; i<NB; ++i) { float z = 3.0f*float(rand()-RAND_MAX/2)/float(RAND_MAX); float alpha = (6.283f / NB)*i; float radius = NB; position[d6] = PFP::VEC3(radius*cos(alpha) + 2*NB+8, radius*sin(alpha), z); d6 = myMap.phi1(d6); } // pour comparer les 2 versions (oreille et basique) //#define NBB 100 // for (int j = 0; j<10000; ++j) // { // Dart d6 = myMap.newFace(NBB); // for (int i = 0; i<NBB; ++i) // { // float alpha = (6.283f / NB)*i; // float radius = NB; // position[d6] = PFP::VEC3(radius*cos(alpha) + 2*NB+8, radius*sin(alpha), 0.1f*j); // d6 = myMap.phi1(d6); // } // } Geom::Vec3f V1(3,3,3); V1.normalize(); Geom::Vec3f V2 = V1 ^ Geom::Vec3f(0,0,-1); Geom::Vec3f V3 = V1 ^ V2; V1 *= 50.0f; V2 *= 50.0f; Dart d5 = myMap.newFace(74); for (int i=0; i<74;++i) { float a = float(rand()-RAND_MAX/2)/float(RAND_MAX) * 0.25f; position[d5] = PFP::VEC3(0.0,60.0,0.0f) + Ifont[2*i] * V1 + Ifont[2*i+1]*V2 + a*V3; d5 = myMap.phi1(d5); } Dart d9 = myMap.newFace(174); for (int i=0; i<174;++i) { float a = float(rand()-RAND_MAX/2)/float(RAND_MAX) * 0.25f; position[d9] = PFP::VEC3(60.0,60.0,0.0f) + Gfont[2*i] * V1 + Gfont[2*i+1]*V2 + a*V3; d9 = myMap.phi1(d9); } // interface: QApplication app(argc, argv); MyQT sqt; // message d'aide sqt.setHelpMsg("Concave face rendering (ears method):\n" "a show all trianglesfaces\n" "a show none trianglesfaces\n" "+ / - show trinagles order rendering (ears creation)"); // bounding box Geom::BoundingBox<PFP::VEC3> bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position); float lWidthObj = std::max<PFP::REAL>(std::max<PFP::REAL>(bb.size(0), bb.size(1)), bb.size(2)); Geom::Vec3f lPosObj = (bb.min() + bb.max()) / PFP::REAL(2); // envoit info BB a l'interface sqt.setParamObject(lWidthObj, lPosObj.data()); // show 1 pour GL context sqt.show(); // update du VBO position (context GL necessaire) sqt.m_positionVBO->updateData(position); // update des primitives du renderer sqt.m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::TRIANGLES, &position); sqt.m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::LINES, &position); sqt.m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::POINTS, &position); // show final pour premier redraw sqt.show(); // et on attend la fin. return app.exec(); }
void Topo3PrimalRender<PFP>::updateData(MAP& mapx, const VertexAttribute<VEC3, MAP>& positions, float ke, float kf) { if (m_attIndex.map() != &mapx) m_attIndex = mapx.template getAttribute<unsigned int, DART, MAP>("dart_index"); if (!m_attIndex.isValid()) m_attIndex = mapx.template addAttribute<unsigned int, DART, MAP>("dart_index"); // m_nbDarts = 0; // for (Dart d = mapx.begin(); d != mapx.end(); mapx.next(d)) // { // m_nbDarts++; // } m_nbDarts = mapx.getNbDarts(); // beta2/3 DartAutoAttribute<VEC3, MAP> fv2(mapx); m_vbo2->bind(); glBufferData(GL_ARRAY_BUFFER, 2*m_nbDarts*sizeof(Geom::Vec3f), 0, GL_STREAM_DRAW); GLvoid* ColorDartsBuffer = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); Geom::Vec3f* colorDartBuf = reinterpret_cast<Geom::Vec3f*>(ColorDartsBuffer); if (m_bufferDartPosition!=NULL) delete m_bufferDartPosition; m_bufferDartPosition = new Geom::Vec3f[2*m_nbDarts]; Geom::Vec3f* positionDartBuf = reinterpret_cast<Geom::Vec3f*>(m_bufferDartPosition); unsigned int posDBI = 0; int nbf = 0; //traverse each face of each volume TraversorF<MAP> traFace(mapx); for (Dart d = traFace.begin(); d != traFace.end(); d = traFace.next()) { std::vector<VEC3> vecPos; vecPos.reserve(16); VEC3 centerFace = Algo::Surface::Geometry::faceCentroidELW<PFP>(mapx, d, positions); //shrink the face float okf = 1.0f - kf; Dart dd = d; do { VEC3 P = centerFace*okf + positions[dd]*kf; vecPos.push_back(P); dd = mapx.phi1(dd); } while (dd != d); unsigned int nb = vecPos.size(); vecPos.push_back(vecPos.front()); // copy the first for easy computation on next loop // compute position of points to use for drawing topo float oke = 1.0f - ke; for (unsigned int i = 0; i < nb; ++i) { VEC3 P = vecPos[i]*ke + vecPos[i+1]*oke; VEC3 Q = vecPos[i+1]*ke + vecPos[i]*oke; // VEC3 PP = 0.52f*P + 0.48f*Q; // VEC3 QQ = 0.52f*Q + 0.48f*P; VEC3 PP = 0.56f*P + 0.44f*Q; VEC3 QQ = 0.56f*Q + 0.44f*P; *positionDartBuf++ = PFP::toVec3f(P); *positionDartBuf++ = PFP::toVec3f(PP); if (mapx.template isBoundaryMarked<3>(d)) { *colorDartBuf++ = m_boundaryDartsColor; *colorDartBuf++ = m_boundaryDartsColor; } else { *colorDartBuf++ = m_dartsColor; *colorDartBuf++ = m_dartsColor; } m_attIndex[d] = posDBI; posDBI+=2; fv2[d] = (P+PP)*0.5f; *positionDartBuf++ = PFP::toVec3f(Q); *positionDartBuf++ = PFP::toVec3f(QQ); Dart dx = mapx.phi3(d); if (mapx.template isBoundaryMarked<3>(dx)) { *colorDartBuf++ = m_boundaryDartsColor; *colorDartBuf++ = m_boundaryDartsColor; } else { *colorDartBuf++ = m_dartsColor; *colorDartBuf++ = m_dartsColor; } m_attIndex[dx] = posDBI; posDBI+=2; fv2[dx] = (Q+QQ)*0.5f; d = mapx.phi1(d); } nbf++; } m_vbo2->bind(); glUnmapBuffer(GL_ARRAY_BUFFER); m_vbo0->bind(); glBufferData(GL_ARRAY_BUFFER, 2*m_nbDarts*sizeof(Geom::Vec3f), m_bufferDartPosition, GL_STREAM_DRAW); // alpha2 m_vbo1->bind(); glBufferData(GL_ARRAY_BUFFER, 2*m_nbDarts*sizeof(Geom::Vec3f), 0, GL_STREAM_DRAW); GLvoid* PositionBuffer2 = glMapBufferARB(GL_ARRAY_BUFFER, GL_READ_WRITE); Geom::Vec3f* positionF2 = reinterpret_cast<Geom::Vec3f*>(PositionBuffer2); m_nbRel2 = 0; for (Dart d = mapx.begin(); d != mapx.end(); mapx.next(d)) { Dart e = mapx.phi2(mapx.phi3(d)); //if (d < e) { *positionF2++ = PFP::toVec3f(fv2[d]); *positionF2++ = PFP::toVec3f(fv2[e]); m_nbRel2++; } } m_vbo1->bind(); glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); }
int main() { // declare a map to handle the mesh MAP myMap; // add position attribute on vertices and get handler on it VertexAttribute<VEC3, MAP> positionAtt = myMap.addAttribute<VEC3, VERTEX, MAP>("position"); if (!positionAtt.isValid()) std::cerr << "impossible to create an attribute with name position (already used ?)"<< std::endl; // create a topo grid of 2x2 squares Algo::Surface::Tilings::Square::Grid<PFP> grid(myMap, 2, 2, true); // and embed it using position attribute grid.embedIntoGrid(positionAtt, 1.,1.,0.); VertexGeneric(myMap,positionAtt); // ATTRIBUTE DECLARATION // add an attribute of type float on orbit EDGE EdgeAttribute<float, MAP> lengthAtt = myMap.addAttribute<float, EDGE, MAP>("length"); if (!lengthAtt.isValid()) std::cerr << "impossible to create the attribute"<< std::endl; computeLengthEdges(myMap,positionAtt,lengthAtt); // add an attribute of type std::string on orbit FACE FaceAttribute<std::string, MAP> nameAtt = myMap.addAttribute<std::string, FACE, MAP>("name"); if (!nameAtt.isValid()) std::cerr << "impossible to create the attribute"<< std::endl; // for complex type use following template (function nameOfType not applicable) EdgeAttribute< NoTypeNameAttribute< std::vector<int> >, MAP> vectAtt = myMap.addAttribute< NoTypeNameAttribute< std::vector<int> >, EDGE, MAP>("vector_of_int"); if (!vectAtt.isValid()) std::cerr << "impossible to create the attribute"<< std::endl; Dart d = myMap.begin(); // define a vertex from a dart Vertex v(d); // define a face from a dart Face f(d); // ATTRIBUTE ACCESS // [] operator can take a dart, a cell (only same off attribute), or an unsigned inf // access to any attributes with darts std::cout << positionAtt[d]<< std::endl; nameAtt[d] = "Hello"; lengthAtt[myMap.phi1(d)] = 54.0f; std::vector<int> vi = {3,5,7,9,11}; vectAtt[d]= vi; vectAtt[d].push_back(11); // access to VertexAttribute with a Vertex std::cout << positionAtt[v]<< std::endl; // access to FaceAttribute with a Face std::cout << nameAtt[f]<< std::endl; // following line does not compile because of wrong cell type // std::cout << positionAtt[f]<< std::endl; // possible to bypass using dart access std::cout << positionAtt[f.dart]<< std::endl; // access with unsigned int is dangerous, index must be obtain with begin/end/next (see dumpAttribute) // COPY, REMOVE, SWAP // possible to have any number of attribute a same ORBIT VertexAttribute<VEC3, MAP> position2Att = myMap.addAttribute<VEC3, VERTEX, MAP>("other_position"); // copy of attribute of same type (linear complexity) myMap.copyAttribute(position2Att,positionAtt); positionAtt[v] += VEC3(0,0,1); computeNewPositions(myMap,positionAtt); dumpAttribute(positionAtt); //check if there is a Vertex Attribute of VEC3 named position => yes testVAbyNames(myMap,"position"); // remove the attribute myMap.removeAttribute(positionAtt); //check if there is a Vertex Attribute of VEC3 named position => no testVAbyNames(myMap,"position"); return 0; }