void Surface_Subdivision_Plugin::CCSubdivision( const QString& mapName, const QString& positionAttributeName, bool interp) { MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName)); if(mh == NULL) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> position = mh->getAttribute<PFP2::VEC3, VERTEX>(positionAttributeName); if(!position.isValid()) return; pythonRecording("CCSubdivision", "", mapName, positionAttributeName,interp); PFP2::MAP* map = mh->getMap(); if (interp) Algo::Surface::Modelisation::CatmullClarkInterpolSubdivision<PFP2>(*map, position); else Algo::Surface::Modelisation::CatmullClarkSubdivision<PFP2>(*map, position); mh->notifyAttributeModification(position); mh->notifyConnectivityModification(); foreach(View* view, mh->getLinkedViews()) view->updateGL(); }
void Surface_DifferentialProperties_Plugin::computeNormal( const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName, bool autoUpdate) { MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName)); if(mh == NULL) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> position = mh->getAttribute<PFP2::VEC3, VERTEX>(positionAttributeName); if(!position.isValid()) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> normal = mh->getAttribute<PFP2::VEC3, VERTEX>(normalAttributeName); if(!normal.isValid()) normal = mh->addAttribute<PFP2::VEC3, VERTEX>(normalAttributeName); PFP2::MAP* map = mh->getMap(); Algo::Surface::Geometry::computeNormalVertices<PFP2>(*map, position, normal); computeNormalLastParameters[mapName] = ComputeNormalParameters(positionAttributeName, normalAttributeName, autoUpdate); mh->notifyAttributeModification(normal); }
void CenterServer::OnAcceptMapServer( Socket* socket ) { /// use ObjectPool::Alloc MapHandler* handler = new MapHandler(); handler->m_CenterServer = this; socket->SetSocketHandler( handler ); handler->SetSocket( socket ); LogInfo( "OnAccept MapServer ip=%s port=%d", socket->GetRemoteIP().c_str(), socket->GetRemotePort() ); }
void Surface_Radiance_Plugin::exportPLY( const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName, const QString& filename) { typedef PFP2::MAP MAP; typedef PFP2::REAL REAL; typedef PFP2::VEC3 VEC3; MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName)); if(mh == NULL) return; VertexAttribute<VEC3, MAP> position = mh->getAttribute<VEC3, VERTEX>(positionAttributeName); if(!position.isValid()) return; VertexAttribute<VEC3, MAP> normal = mh->getAttribute<VEC3, VERTEX>(normalAttributeName); if(!normal.isValid()) return; VertexAttribute<Utils::SphericalHarmonics<REAL, VEC3>, MAP> radiance = h_mapParameterSet[mh].radiance; if(!radiance.isValid()) return; // open file std::ofstream out ; out.open(filename.toStdString(), std::ios::out | std::ios::binary) ; if (!out.good()) { CGoGNerr << "Unable to open file " << CGoGNendl ; return ; } MAP* map = mh->getMap(); unsigned int nbDarts = map->getNbDarts() ; std::vector<unsigned int> facesSize ; std::vector<std::vector<unsigned int> > facesIdx ; facesSize.reserve(nbDarts/3) ; facesIdx.reserve(nbDarts/3) ; std::map<unsigned int, unsigned int> vIndex ; unsigned int vCpt = 0 ; std::vector<unsigned int> vertices ; vertices.reserve(nbDarts/6) ; // Go over all faces CellMarker<MAP, VERTEX> markV(*map) ; TraversorF<MAP> t(*map) ; for(Dart d = t.begin(); d != t.end(); d = t.next()) { std::vector<unsigned int> fidx ; fidx.reserve(8) ; unsigned int degree = 0 ; Traversor2FV<MAP> tfv(*map, d) ; for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next()) { ++degree ; unsigned int vNum = map->getEmbedding<VERTEX>(it) ; if(!markV.isMarked(it)) { markV.mark(it) ; vIndex[vNum] = vCpt++ ; vertices.push_back(vNum) ; } fidx.push_back(vIndex[vNum]) ; } facesSize.push_back(degree) ; facesIdx.push_back(fidx) ; } // Start writing the file out << "ply" << std::endl ; // test endianness union { uint32_t i ; char c[4] ; } bint = {0x01020304} ; if (bint.c[0] == 1) // big endian out << "format binary_big_endian 1.0" << std::endl ; else out << "format binary_little_endian 1.0" << std::endl ; out << "comment File generated by the CGoGN library" << std::endl ; out << "comment See : http://cgogn.unistra.fr/" << std::endl ; out << "comment or contact : [email protected]" << std::endl ; // Vertex elements out << "element vertex " << vertices.size() << std::endl ; std::string nameOfTypePly_REAL(nameOfTypePly(position[0][0])) ; out << "property " << nameOfTypePly_REAL << " x" << std::endl ; out << "property " << nameOfTypePly_REAL << " y" << std::endl ; out << "property " << nameOfTypePly_REAL << " z" << std::endl ; out << "property " << nameOfTypePly_REAL << " nx" << std::endl ; out << "property " << nameOfTypePly_REAL << " ny" << std::endl ; out << "property " << nameOfTypePly_REAL << " nz" << std::endl ; int res = Utils::SphericalHarmonics<REAL, VEC3>::get_resolution() ; for (int l = 0 ; l <= res ; ++l) { for (int m = -l ; m <= l ; ++m) { out << "property " << nameOfTypePly_REAL << " SHcoef_" << l << "_" << m << "_r" << std::endl ; out << "property " << nameOfTypePly_REAL << " SHcoef_" << l << "_" << m << "_g" << std::endl ; out << "property " << nameOfTypePly_REAL << " SHcoef_" << l << "_" << m << "_b" << std::endl ; } } // Face element out << "element face " << facesSize.size() << std::endl ; out << "property list uint8 " << nameOfTypePly(facesIdx[0][0]) << " vertex_indices" << std::endl ; out << "end_header" << std::endl ; // binary vertices for(unsigned int i = 0; i < vertices.size(); ++i) { const VEC3& p = position[vertices[i]] ; out.write((char*)(&(p[0])), sizeof(p)) ; const VEC3& n = normal[vertices[i]] ; out.write((char*)(&(n[0])), sizeof(n)) ; for (int l=0 ; l <= res ; ++l) { for (int m=-l ; m <= l ; ++m) { const VEC3& r = radiance[vertices[i]].get_coef(l,m) ; out.write((char*)(&(r[0])), sizeof(r)) ; } } } // binary faces for(unsigned int i = 0; i < facesSize.size(); ++i) { uint8_t nbe = facesSize[i] ; out.write((char*)(&nbe), sizeof(uint8_t)) ; out.write((char*)(&(facesIdx[i][0])), facesSize[i] * sizeof(facesIdx[i][0])) ; } out.close() ; this->pythonRecording("exportPLY", "", mapName, positionAttributeName, normalAttributeName, filename); }
void Surface_Radiance_Plugin::decimate(const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName, float decimationGoal, bool halfCollapse, bool exportMeshes) { MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName)); if(mh == NULL) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> position = mh->getAttribute<PFP2::VEC3, VERTEX>(positionAttributeName); if(!position.isValid()) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> normal = mh->getAttribute<PFP2::VEC3, VERTEX>(normalAttributeName); if(!normal.isValid()) return; PFP2::MAP* map = mh->getMap(); unsigned int nbVertices = Algo::Topo::getNbOrbits<VERTEX>(*map); MapParameters& mapParams = h_mapParameterSet[mh]; if (halfCollapse) { if (mapParams.positionApproximator == NULL) { mapParams.positionApproximator = new Algo::Surface::Decimation::Approximator_HalfCollapse<PFP2, PFP2::VEC3>(*map, position); } if (mapParams.normalApproximator == NULL) { mapParams.normalApproximator = new Algo::Surface::Decimation::Approximator_HalfCollapse<PFP2, PFP2::VEC3>(*map, normal); } if (mapParams.radianceApproximator == NULL) { mapParams.radianceApproximator = new Algo::Surface::Decimation::Approximator_HalfCollapse<PFP2, Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3> >(*map, mapParams.radiance); } if (mapParams.selector == NULL) { mapParams.selector = new HalfEdgeSelector_Radiance<PFP2>( *map, position, normal, mapParams.radiance, *(Algo::Surface::Decimation::Approximator<PFP2, PFP2::VEC3, DART>*)(mapParams.positionApproximator), *(Algo::Surface::Decimation::Approximator<PFP2, PFP2::VEC3, DART>*)(mapParams.normalApproximator), *(Algo::Surface::Decimation::Approximator<PFP2, Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>, DART>*)(mapParams.radianceApproximator) ); } } else { if (mapParams.positionApproximator == NULL) { mapParams.positionApproximator = new Algo::Surface::Decimation::Approximator_QEM<PFP2>(*map, position); } if (mapParams.normalApproximator == NULL) { mapParams.normalApproximator = new Algo::Surface::Decimation::Approximator_InterpolateAlongEdge<PFP2, PFP2::VEC3>( *map, normal, position, ((Algo::Surface::Decimation::Approximator<PFP2, PFP2::VEC3, EDGE>*)(mapParams.positionApproximator))->getApproximationResultAttribute() ); } if (mapParams.radianceApproximator == NULL) { mapParams.radianceApproximator = new Algo::Surface::Decimation::Approximator_InterpolateAlongEdge<PFP2, Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3> >( *map, mapParams.radiance, position, ((Algo::Surface::Decimation::Approximator<PFP2, PFP2::VEC3, EDGE>*)(mapParams.positionApproximator))->getApproximationResultAttribute() ); } if (mapParams.selector == NULL) { mapParams.selector = new EdgeSelector_Radiance<PFP2>( *map, position, normal, mapParams.radiance, *(Algo::Surface::Decimation::Approximator<PFP2, PFP2::VEC3, EDGE>*)(mapParams.positionApproximator), *(Algo::Surface::Decimation::Approximator<PFP2, PFP2::VEC3, EDGE>*)(mapParams.normalApproximator), *(Algo::Surface::Decimation::Approximator<PFP2, Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>, EDGE>*)(mapParams.radianceApproximator) ); mapParams.selector = new Algo::Surface::Decimation::EdgeSelector_QEM<PFP2>( *map, position, *(Algo::Surface::Decimation::Approximator<PFP2, PFP2::VEC3, EDGE>*)(mapParams.positionApproximator) ); } } std::vector<Algo::Surface::Decimation::ApproximatorGen<PFP2>*> approximators; approximators.push_back(mapParams.positionApproximator); approximators.push_back(mapParams.normalApproximator); approximators.push_back(mapParams.radianceApproximator); exportNbVert.clear(); if (exportMeshes) { unsigned int goalNbV = decimationGoal * nbVertices; unsigned int curNbV = nbVertices / 2; while (curNbV > goalNbV) { exportNbVert.push_back(curNbV); curNbV /= 2; } exportNbVert.push_back(goalNbV); nextExportIndex = 0; } std::cout << "nb vert -> " << nbVertices << std::endl; for (unsigned int v : exportNbVert) { std::cout << v << std::endl; } m_currentlyDecimatedMap = mh; m_currentDecimationHalf = halfCollapse; Algo::Surface::Decimation::decimate<PFP2>(*map, mapParams.selector, approximators, decimationGoal * nbVertices, true, NULL, (void (*)(void*, const void*))(Surface_Radiance_Plugin::checkNbVerticesAndExport), (void*)(this)); m_currentlyDecimatedMap = NULL; mh->notifyConnectivityModification(); mh->notifyAttributeModification(position); }
MapHandlerGen* Surface_Radiance_Plugin::importFromFile(const QString& fileName) { QFileInfo fi(fileName); if(fi.exists()) { MapHandlerGen* mhg = m_schnapps->addMap(fi.baseName(), 2); if(mhg) { MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(mhg); PFP2::MAP* map = mh->getMap(); MeshTablesSurface_Radiance importer(*map); if (!importer.importPLY<Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3> >(fileName.toStdString())) { std::cout << "could not import " << fileName.toStdString() << std::endl; return NULL; } CGoGN::Algo::Surface::Import::importMesh<PFP2>(*map, importer); // get vertex position attribute VertexAttribute<PFP2::VEC3, PFP2::MAP> position = map->getAttribute<PFP2::VEC3, VERTEX, PFP2::MAP>("position") ; VertexAttribute<PFP2::VEC3, PFP2::MAP> normal = map->getAttribute<PFP2::VEC3, VERTEX, PFP2::MAP>("normal"); mh->registerAttribute(position); mh->registerAttribute(normal); MapParameters& mapParams = h_mapParameterSet[mhg]; mapParams.nbVertices = Algo::Topo::getNbOrbits<VERTEX>(*map); mapParams.radiance = map->getAttribute<Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>, VERTEX, PFP2::MAP>("radiance") ; mapParams.radianceTexture = new Utils::Texture<2, Geom::Vec3f>(GL_FLOAT); mapParams.param = map->checkAttribute<Geom::Vec2i, VERTEX, PFP2::MAP>("param"); // create texture unsigned int nbv_nbc = Algo::Topo::getNbOrbits<VERTEX>(*map) * Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>::get_nb_coefs(); unsigned int size = 1; while (size * size < nbv_nbc) size <<= 1; mapParams.radianceTexture->create(Geom::Vec2i(size, size)); // fill texture unsigned int count = 0; foreach_cell<VERTEX>(*map, [&] (Vertex v) { unsigned int i = count / size; unsigned int j = count % size; mapParams.param[v] = Geom::Vec2i(i, j) ; // first index for current vertex for (int l = 0 ; l <= Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>::get_resolution() ; ++l) { for (int m = -l ; m <= l ; ++m) { i = count / size; j = count % size; (*(mapParams.radianceTexture))(i,j) = mapParams.radiance[v].get_coef(l, m); ++count; } } }) ; // resulting texture : SH00_vx0, SH1-1_vx0, ..., SHlm_vx0, SH00_vx1, SH1-1_vx1, ..., SHlm_vx1, etc. // resulting param : param[vxI] points to SH00_vxI // the size of the texture is needed to know where to do the divisions and modulos. mapParams.radianceTexture->update(); // uncomment this line to be able to load multiple objects with different SH basis // (decimation will be unavailable) // map->removeAttribute(mapParams.radiance); mapParams.paramVBO = new Utils::VBO(); mapParams.paramVBO->updateData(mapParams.param); mapParams.radiancePerVertexShader = new Utils::ShaderRadiancePerVertex(Utils::SphericalHarmonics<PFP2::REAL, PFP2::VEC3>::get_resolution()); registerShader(mapParams.radiancePerVertexShader); } this->pythonRecording("importFile", mhg->getName(), fi.baseName()); return mhg; } else return NULL; }
void Surface_DifferentialProperties_Plugin::computeCurvature( const QString& mapName, const QString& positionAttributeName, const QString& normalAttributeName, const QString& KmaxAttributeName, const QString& kmaxAttributeName, const QString& KminAttributeName, const QString& kminAttributeName, const QString& KnormalAttributeName, bool compute_kmean, bool compute_kgaussian, bool autoUpdate) { MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_schnapps->getMap(mapName)); if(mh == NULL) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> position = mh->getAttribute<PFP2::VEC3, VERTEX>(positionAttributeName); if(!position.isValid()) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> normal = mh->getAttribute<PFP2::VEC3, VERTEX>(normalAttributeName); if(!normal.isValid()) return; VertexAttribute<PFP2::VEC3, PFP2::MAP> Kmax = mh->getAttribute<PFP2::VEC3, VERTEX>(KmaxAttributeName); if(!Kmax.isValid()) Kmax = mh->addAttribute<PFP2::VEC3, VERTEX>(KmaxAttributeName); VertexAttribute<PFP2::REAL, PFP2::MAP> kmax = mh->getAttribute<PFP2::REAL, VERTEX>(kmaxAttributeName); if(!kmax.isValid()) kmax = mh->addAttribute<PFP2::REAL, VERTEX>(kmaxAttributeName); VertexAttribute<PFP2::VEC3, PFP2::MAP> Kmin = mh->getAttribute<PFP2::VEC3, VERTEX>(KminAttributeName); if(!Kmin.isValid()) Kmin = mh->addAttribute<PFP2::VEC3, VERTEX>(KminAttributeName); VertexAttribute<PFP2::REAL, PFP2::MAP> kmin = mh->getAttribute<PFP2::REAL, VERTEX>(kminAttributeName); if(!kmin.isValid()) kmin = mh->addAttribute<PFP2::REAL, VERTEX>(kminAttributeName); VertexAttribute<PFP2::VEC3, PFP2::MAP> Knormal = mh->getAttribute<PFP2::VEC3, VERTEX>(KnormalAttributeName); if(!Knormal.isValid()) Knormal = mh->addAttribute<PFP2::VEC3, VERTEX>(KnormalAttributeName); EdgeAttribute<PFP2::REAL, PFP2::MAP> edgeAngle = mh->getAttribute<PFP2::REAL, EDGE>("edgeAngle"); if(!edgeAngle.isValid()) edgeAngle = mh->addAttribute<PFP2::REAL, EDGE>("edgeAngle"); PFP2::MAP* map = mh->getMap(); Algo::Surface::Geometry::computeAnglesBetweenNormalsOnEdges<PFP2>(*map, position, edgeAngle); Algo::Surface::Geometry::computeCurvatureVertices_NormalCycles_Projected<PFP2>(*map, 0.01f * mh->getBBdiagSize(), position, normal, edgeAngle, kmax, kmin, Kmax, Kmin, Knormal); computeCurvatureLastParameters[mapName] = ComputeCurvatureParameters( positionAttributeName, normalAttributeName, KmaxAttributeName, kmaxAttributeName, KminAttributeName, kminAttributeName, KnormalAttributeName, compute_kmean, compute_kgaussian, autoUpdate); mh->notifyAttributeModification(Kmax); mh->notifyAttributeModification(kmax); mh->notifyAttributeModification(Kmin); mh->notifyAttributeModification(kmin); mh->notifyAttributeModification(Knormal); if(compute_kmean) { VertexAttribute<PFP2::REAL, PFP2::MAP> kmean = mh->getAttribute<PFP2::REAL, VERTEX>("kmean"); if(!kmean.isValid()) kmean = mh->addAttribute<PFP2::REAL, VERTEX>("kmean"); for(unsigned int i = kmin.begin(); i != kmin.end(); kmin.next(i)) kmean[i] = (kmin[i] + kmax[i]) / 2.0; mh->notifyAttributeModification(kmean); } if(compute_kgaussian) { VertexAttribute<PFP2::REAL, PFP2::MAP> kgaussian = mh->getAttribute<PFP2::REAL, VERTEX>("kgaussian"); if(!kgaussian.isValid()) kgaussian = mh->addAttribute<PFP2::REAL, VERTEX>("kgaussian"); for(unsigned int i = kmin.begin(); i != kmin.end(); kmin.next(i)) kgaussian[i] = kmin[i] * kmax[i]; mh->notifyAttributeModification(kgaussian); } }