#include "CurvesLoader.hpp" string CurvesLoader::currentCurveType; vector* CurvesLoader::pointsBuffer; vector CurvesLoader::NURBSes; vector CurvesLoader::beziers; unsigned int CurvesLoader::NURBSOrder; NURBSType CurvesLoader::NURBS_TYPE; vector* CurvesLoader::NURBSWeights; char CurvesLoader::lineHeader[128]; char* CurvesLoader::res; FILE* CurvesLoader::file; std::smatch CurvesLoader::pieces; void CurvesLoader::beginCurve(string str, std::smatch pieces, std::regex regex) { pointsBuffer = new vector(); NURBSWeights = new vector(); NURBS_TYPE = NURBSType::BASIC; //si inizia una patch di BEZIER if (pieces[1].str() == "BEZIER") { //std::cout << "next is BEZIER" << std::endl; currentCurveType = "BEZIER"; } //si inizia una NURBS else if (pieces[1].str() == "NURBS") { //std::cout << "next is NURBS" << std::endl; currentCurveType = "NURBS"; res = fgets(lineHeader, 128, file); // read curve multiplicity str = lineHeader; std::regex regex("\\s*order (\\d)\\s*(clamped|cyclic)?\\s*(\\n)?"); if (res == NULL || !std::regex_match(str, pieces, regex)) { throw "expected NURBS order"; } else { NURBSOrder = stoi(pieces[1]); if (pieces.length() > 2) { if (pieces[2].str() == "clamped") { NURBS_TYPE = NURBSType::CLAMPED; } else if (pieces[2].str() == "cyclic") { NURBS_TYPE = NURBSType::CYCLIC; } } else { NURBS_TYPE = NURBSType::BASIC; } std::cout << res << std::endl; } //std::cout << "parsed order : " << NURBSOrder << std::endl; } } NURBS* CurvesLoader::BasicNURBS() { unsigned int nFunctions = pointsBuffer->size(); unsigned int totalElements = NURBSOrder + nFunctions; vector* intervals = new vector(); for (int i = 0; i <= totalElements; i++) intervals->push_back((float) i / totalElements); vector* multiplicities = new vector; for (int i = 0; i < pointsBuffer->size(); i++) multiplicities->push_back(1); return new NURBS(NURBSOrder, pointsBuffer, NURBSWeights, intervals, multiplicities); } NURBS* CurvesLoader::ClampedNURBS() { unsigned int nFunctions = pointsBuffer->size(); vector* intervals = new vector(); for (int i = 0; i <= NURBSOrder; i++) intervals->push_back(0); for (int i = 1; i <= nFunctions - NURBSOrder; i++) intervals->push_back((float)i / (nFunctions - NURBSOrder)); for (int i = 0; i < NURBSOrder; i++) intervals->push_back(1); vector* multiplicities = new vector; for (int i = 0; i < pointsBuffer->size(); i++) multiplicities->push_back(1); return new NURBS(NURBSOrder, pointsBuffer, NURBSWeights, intervals, multiplicities); } NURBS* CurvesLoader::CyclicNURBS() { for (int i = 0; i < NURBSOrder; i++) { pointsBuffer->push_back(pointsBuffer->at(i)); NURBSWeights->push_back(NURBSWeights->at(i)); } unsigned int nFunctions = pointsBuffer->size(); unsigned int totalElements = NURBSOrder + nFunctions; vector* intervals = new vector(); for (int i = 0; i <= totalElements; i++) intervals->push_back((float) i/ totalElements); vector* multiplicities = new vector; for (int i = 0; i < pointsBuffer->size(); i++) multiplicities->push_back(1); return new NURBS(NURBSOrder, pointsBuffer, NURBSWeights, intervals, multiplicities); } void CurvesLoader::closeNURBS(){ try { switch (NURBS_TYPE) { case NURBSType::BASIC : std::cout << "NURBS was BASIC" << std::endl; NURBSes.push_back(BasicNURBS()); break; case NURBSType::CLAMPED : std::cout << "NURBS was CLAMPED" << std::endl; NURBSes.push_back(ClampedNURBS()); break; case NURBSType::CYCLIC : std::cout << "NURBS was CYCLIC" << std::endl; NURBSes.push_back(CyclicNURBS()); break; } } catch (std::invalid_argument e) { std::cout << e.what() << std::endl; } } void CurvesLoader::closeBezier() { vector* intervals = new vector(); int nIntervals = pointsBuffer->size() / 4; intervals->push_back(0); for (int i = 1; i <= nIntervals; i++) intervals->push_back((float)i / nIntervals); beziers.push_back(new Bezier3Segments(pointsBuffer, intervals)); } void CurvesLoader::closePendingCurve() { if (currentCurveType == "BEZIER") { closeBezier(); } else if (currentCurveType == "NURBS") { closeNURBS(); } } void CurvesLoader::parseVertexData(string str) { vector vecComponents = vector(); std::regex regex("-?\\d+.\\d+"); while (std::regex_search(str, pieces, regex)) { float entry = stof(pieces[0], NULL); //potevi evitare la regex vecComponents.push_back(entry); str = pieces.suffix().str(); } glm::vec3 vec(vecComponents[0], vecComponents[1], vecComponents[2]); pointsBuffer->push_back(vec); if (currentCurveType == "NURBS") { NURBSWeights->push_back(vecComponents[3]); } } bool CurvesLoader::loadCurves(std::string path, vector& curves) { currentCurveType = "NONE"; pointsBuffer = new vector(); NURBSWeights = new vector(); file = fopen(&path[0], "r"); if (file == NULL) { printf("Impossible to open the curve file ! Are you in the right path ?\n"); getchar(); return false; } while (1) { res = fgets(lineHeader, 128, file); // read the first word of the line // EOF = End Of File. Store pending curve and quit the loop. if (res == NULL) { closePendingCurve(); //what if there was no pending curve? (aka return false) break; } string str = lineHeader; std::regex regex("\\s*curve \\d+ : (BEZIER|NURBS)\\n"); //inizia una curva (la prima o una nuova) if (std::regex_match(str, pieces, regex)) { closePendingCurve(); beginCurve(str, pieces, regex); } //deve essere materiale inerente la curva in costruzione else { std::regex regex("\\s*(-?\\d+.\\d+)(( , -?\\d+.\\d+)+)\\s*(\\n)?"); //sono dati di un vertice if (std::regex_match(str, pieces, regex)){ parseVertexData(str); } else { std::cout << "unrecognized line : " << str << std::endl; } } } std::cout << "trovate " << beziers.size() << " curve di bezier" << std::endl << "e " << NURBSes.size() << " NURBS" << std::endl; for (Bezier3Segments* el : beziers) curves.push_back(el); for (NURBS* el : NURBSes) curves.push_back(el); /* !!! only the file existence gets checked */ return true; }