bool KAbstractObjParserPrivate::parse() { for (;;) { switch (nextToken()) { case PT_ERROR: qFatal("Encountered an error! Aborting"); return false; case PT_EOF: return true; case PT_VERTEX: parseVertex(); break; case PT_TEXTURE: parseTexture(); break; case PT_NORMAL: parseNormal(); break; case PT_PARAMETER: parseParameter(); break; case PT_FACE: parseFace(); case PT_ENDSTATEMENT: break; } } }
void parse(std::ifstream& file, ObjStore& obj) { std::string line; std::stringstream lineStream; char firstChar; std::cout << "Parsing Obj!" << std::endl; while ( std::getline( file, line ) ) { // reject empty lines if ( line.empty() ) { continue; } // make stream from line lineStream.clear(); lineStream.str(line); // check first char to determine type lineStream.get(firstChar); if (firstChar == 'v') { parseVertex(lineStream, obj); } else if (firstChar == 'f') { parseFace(lineStream, obj); } } }
void Obj2::load(std::string const& path) { ifstream file; string work; file.open(path.c_str(), ios::in); //check ouverture if (!file.good()) { throw FileError(0,"Error in OBJ load : \n\timpossible to open " + path + "."); } objects.clear(); vertices.clear(); //boucle de parcours pour tout le fichier int cptr = 0; Object *currentObject = nullptr; while (!file.eof()) { cptr++; file >> work;//premier mot de la ligne //cas face if (work == "f") {//on ne désespère pas. un jour on pourra switcher sur des strings. ptt. if (currentObject == nullptr) throw FileError(1,"Error in OBJ load : \n\tface before first object at line " + to_string(cptr)); getline(file, work); currentObject->addFace(parseFace(work)); }//cas vertice else if (work == "v") { getline(file, work); addVertex(parseVertex(work)); }//cas objet else if (work == "o") { file >> work; if (currentObject != nullptr) { currentObject->setDimension((currentObject->nbrFaces() == 6) ? 0 : 1); addObject(*currentObject); }currentObject = new Object(work, 1); }//cas commentaire else if (work == "#") {
void ModelLoader::parseLine(char *line) { //check for an empty string if(!strlen(line)) { return; } char *linetype; linetype = strtok(strdup(line), " "); if(!strcmp(linetype, "v")) { parseVertex(line); //line is a vertex } else if(!strcmp(linetype, "vn")) { parseNormal(line); //line is a normal } else if(!strcmp(linetype, "vt")) { parseTexel(line); //line is a texel } else if(!strcmp(linetype, "f")) { parseFace(line); //line is a face } return; }
void WFObject::parseLine(char *line) { if(!strlen(line)) { return; } char *lineType; lineType = strtok(_strdup(line), " "); // Decide what to do if(!strcmp(lineType, "v")) // Vertex { parseVertex(line); } else if (!strcmp(lineType, "vt")) { parseTexture(line); } else if(!strcmp(lineType, "vn")) // Normal { parseNormal(line); } else if(!strcmp(lineType, "f")) // Face { parseFace(line); } return; }
void Mesh::parseLine(std::stringstream&& sin) { std::string s; sin >> s; if (s.compare("v") == 0) parseVertex(sin); else if (s.compare("vt") == 0) parseTexcoord(sin); else if (s.compare("vn") == 0) parseNormal(sin); else if (s.compare("f") == 0) parseFace(sin); }
void Geometry::parseObjFile(const std::string filePath, std::vector<GLfloat>& vboData, std::vector<GLushort>& iboData) { //temporary save values in arrays std::vector<glm::vec3> vertices; std::vector<glm::vec3> normals; //save which data vbo already contains std::list<IndexCombination> combinations; //save next vbo index to use GLushort nextVboIndex = 0; //open file std::ifstream objFile; objFile.exceptions(std::ifstream::badbit | std::ifstream::failbit); objFile.open(filePath); std::string line; while (!objFile.eof()) { try { std::getline(objFile, line); } catch (const std::exception &ex) { if (!objFile.eof()) { throw ex; } else { continue; } } std::istringstream lstream(line); std::string type; lstream >> type; if (type.compare("v") == 0) { parseVertex(lstream, vertices); } else if (type.compare("vn") == 0) { parseNormal(lstream, normals); } else if (type.compare("f") == 0) { parseFace(lstream, vboData, iboData, vertices, normals, &nextVboIndex, combinations); } else if (type.compare("s") == 0) { //ignore line } else if (type.compare("o") == 0) { //ignore line } else if (type.compare("#") == 0) { //ignore line } else { throw std::logic_error("Unknown start of line"); } } objFile.close(); }
bool MapParser::parseFaces(const BBox& worldBounds, Model::FaceList& faces) { size_t oldSize = faces.size(); try { Model::Face* face = NULL; while ((face = parseFace(worldBounds)) != NULL) faces.push_back(face); return !faces.empty(); } catch (MapParserException e) { Utility::deleteAll(faces, oldSize); m_tokenizer.reset(); return false; } }
void Model::parseMesh(std::string fileName) { std::string line; std::ifstream myFile(fileName.c_str()); if (myFile.is_open()) { while (getline(myFile, line)) { if (line.at(0) == 'o') { meshName = parseName(line); } else if (line.at(0) == 'v' && line.at(1) == ' ') { vertexArray.push_back(parseVertex(line)); } else if (line.at(0) == 'f') { std::vector<std::string> elements = split(line, ' '); if ((elements.size() - 1) == 4) { quadArray.push_back(parseFace(elements)); } else if ((elements.size() - 1) == 3) { triArray.push_back(parseFace(elements)); } elements.clear(); } else { // N-Gons } } } myFile.close(); }
int objLoad(char* filePath) { FILE* file = fopen(filePath, "r"); char* line = (char*)calloc(LINE_SIZE, sizeof(char)); char* token = NULL, * delim = " \n\t"; int vertexCount = 0, textureCount = 0, normalCount = 0, faceCount = 0; while(fgets(line, LINE_SIZE, file) != NULL) { if(prefix("vt", line)) ++textureCount; else if(prefix("vn", line)) ++normalCount; else if(prefix("v", line)) ++vertexCount; else if(prefix("f", line)) ++faceCount; } rewind(file); obj* object = (obj*)calloc(1, sizeof(obj)); object->faceCount = faceCount; object->vertexCount = vertexCount; object->vertices = (vec3*)calloc(vertexCount, sizeof(vec3)); object->shared = (int*)calloc(vertexCount, sizeof(int)); object->normals = (vec3*)calloc(normalCount, sizeof(vec3)); object->tangents = (vec3*)calloc(vertexCount, sizeof(vec3)); object->bitangents = (vec3*)calloc(vertexCount, sizeof(vec3)); object->textures = (vec2*)calloc(textureCount, sizeof(vec2)); object->faces = (face*)calloc(faceCount, sizeof(face)); int vertexTally = 0, normalTally = 0, textureTally = 0, faceTally = 0; while(fgets(line, LINE_SIZE, file) != NULL) { if(prefix("vt", line)) { parseVec2(line, &object->textures[textureTally]); object->textures[textureTally].y = 1.0 - object->textures[textureTally].y; ++textureTally; } else if(prefix("vn", line)) parseVec3(line, &object->normals[normalTally++]); else if(prefix("v", line)) parseVec3(line, &object->vertices[vertexTally++]); else if(prefix("f", line)) parseFace(line, object->faces[faceTally++]); } uniqueMap(object); free(line); fclose(file); int index = nextIndex(); objects[index] = object; return index; }
Model::Brush* MapParser::parseBrush(const BBox& worldBounds, Utility::ProgressIndicator* indicator) { Token token = m_tokenizer.nextToken(); if (token.type() == TokenType::Eof) return NULL; expect(TokenType::OBrace | TokenType::CBrace, token); if (token.type() == TokenType::CBrace) return NULL; Model::Brush* brush = new Model::Brush(worldBounds); brush->setFilePosition(token.line()); while ((token = m_tokenizer.nextToken()).type() != TokenType::Eof) { switch (token.type()) { case TokenType::OParenthesis: { m_tokenizer.pushToken(token); Model::Face* face = parseFace(worldBounds); if (face != NULL && brush != NULL) { if (!brush->addFace(face)) { m_console.warn("Skipping malformed brush at line %i", brush->filePosition()); delete brush; brush = NULL; } } else { delete face; } break; } case TokenType::CBrace: if (indicator != NULL) indicator->update(static_cast<int>(token.position())); if (brush != NULL && !brush->closed()) { m_console.warn("Non-closed brush at line %i", brush->filePosition()); // delete brush; // brush = NULL; } return brush; default: delete brush; throw MapParserException(token, TokenType::OParenthesis | TokenType::CParenthesis); } } return NULL; }
bool rcMeshLoaderObj::load(const char* filename) { char* buf = 0; FILE* fp = fopen(filename, "rb"); if (!fp) return false; fseek(fp, 0, SEEK_END); int bufSize = ftell(fp); fseek(fp, 0, SEEK_SET); buf = new char[bufSize]; if (!buf) { fclose(fp); return false; } fread(buf, bufSize, 1, fp); fclose(fp); char* src = buf; char* srcEnd = buf + bufSize; char row[512]; int face[32]; float x,y,z; int nv; int vcap = 0; int tcap = 0; while (src < srcEnd) { // Parse one row row[0] = '\0'; src = parseRow(src, srcEnd, row, sizeof(row)/sizeof(char)); // Skip comments if (row[0] == '#') continue; if (row[0] == 'v' && row[1] != 'n' && row[1] != 't') { // Vertex pos sscanf(row+1, "%f %f %f", &x, &y, &z); addVertex(x, y, z, vcap); } if (row[0] == 'f') { // Faces nv = parseFace(row+1, face, 32, m_vertCount); for (int i = 2; i < nv; ++i) { const int a = face[0]; const int b = face[i-1]; const int c = face[i]; if (a < 0 || a >= m_vertCount || b < 0 || b >= m_vertCount || c < 0 || c >= m_vertCount) continue; addTriangle(a, b, c, tcap); } } } delete [] buf; // Calculate normals. m_normals = new float[m_triCount*3]; for (int i = 0; i < m_triCount*3; i += 3) { const float* v0 = &m_verts[m_tris[i]*3]; const float* v1 = &m_verts[m_tris[i+1]*3]; const float* v2 = &m_verts[m_tris[i+2]*3]; float e0[3], e1[3]; for (int j = 0; j < 3; ++j) { e0[j] = v1[j] - v0[j]; e1[j] = v2[j] - v0[j]; } float* n = &m_normals[i]; n[0] = e0[1]*e1[2] - e0[2]*e1[1]; n[1] = e0[2]*e1[0] - e0[0]*e1[2]; n[2] = e0[0]*e1[1] - e0[1]*e1[0]; float d = sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]); if (d > 0) { d = 1.0f/d; n[0] *= d; n[1] *= d; n[2] *= d; } } strncpy(m_filename, filename, sizeof(m_filename)); m_filename[sizeof(m_filename)-1] = '\0'; return true; }
Mesh *Mesh::fromObjFile(QString filename) { QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return 0; Mesh *M = new Mesh(); vector<Vector3f> normals; //first pass to add all vertices and normals to mesh while (!file.atEnd()) { QByteArray lineBytes = file.readLine(); if (lineBytes.at(0) == 'v' && lineBytes.at(1) == 'n') { // parse normal if line starts with 'vn' Vector3f normal; if (!parseCoordinate(QString(lineBytes), normal)) { delete M; return false; } normals.push_back(normal); } else if (lineBytes.at(0) == 'v' && lineBytes.at(1) == ' ') { // parse vertex if line starts with just 'v' Vertex V; if (!parseCoordinate(QString(lineBytes), V.pos)) { delete M; return false; } M->m_vertices.push_back(V); } } //second pass to add faces to the mesh file.reset(); while (!file.atEnd()) { QByteArray lineBytes = file.readLine(); if (lineBytes.at(0) == 'f') { uint V[4]; uint N[4]; bool hasNormals; if (!parseFace(QString(lineBytes), V, N, hasNormals)) { delete M; return false; } if (hasNormals) { //use normals if they are provided Vector3f faceNormals[4]; for (uint i = 0; i < 4; i++) { if (N[i] < normals.size()) faceNormals[i] = normals[N[i]]; } M->addFace(V[0],V[1],V[2],V[3], faceNormals); } else { //interpolate normals if they are not provided M->addFace(V[0],V[1],V[2],V[3]); } } } return M; }
GLLObjFile::GLLObjFile(CFURLRef location) { std::string filename = GLLStringFromFileURL(location); int fdes = ::open(filename.c_str(), O_RDONLY); if (fdes < 0) { throw std::runtime_error("Could not open file"); } struct stat statistics; if (fstat(fdes, &statistics) < 0) { close(fdes); throw std::runtime_error("Could not get file size"); } const char *buffer = (const char *) mmap(nullptr, statistics.st_size, PROT_READ, MAP_PRIVATE, fdes, 0); close(fdes); const char *current = buffer; const char *end = &buffer[statistics.st_size]; materialLibraryURLs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); std::string activeMaterial(""); unsigned activeMaterialStart = 0; bool hasFirstMaterial = false; while(current != end) { while (current != end && (*current == ' ' || *current == '\n' || *current == '\r')) { current++; } if (current == end) break; switch (*current) { case 'f': parseFace(current, end); break; case 'v': current += 1; switch (*current) { case 'n': // Normals current += 1; parseVector(current, end, normals, 3); break; case 't': // Tex coords current += 1; parseVector(current, end, texCoords, 2); break; case 'c': // Colors current += 1; parseVector(current, end, colors, 4); break; case ' ': // Vertex parseVector(current, end, vertices, 3); break; default: skipToEndOfLine(current, end); break; } break; case 'm': if (followsString(current, end, "mtllib")) { std::string mtllib = stringToEndOfLine(current, end); try { CFURLRef mtllibLocation = GLLCreateURLFromString(mtllib, location); CFArrayAppendValue(materialLibraryURLs, mtllibLocation); CFRelease(mtllibLocation); } catch (std::exception &e) { std::cerr << "Ignoring mtllib: " << e.what() << std::endl; } } else { skipToEndOfLine(current, end); } break; case 'u': if (followsString(current, end, "usemtl")) { if (hasFirstMaterial) { // End previous material run materialRanges.push_back(MaterialRange(activeMaterialStart, (unsigned) originalIndices.size(), activeMaterial)); } else hasFirstMaterial = true; current += 1; activeMaterial = stringToEndOfLine(current, end); activeMaterialStart = (unsigned) originalIndices.size(); } else { skipToEndOfLine(current, end); } break; case '#': // Comment default: skipToEndOfLine(current, end); break; } } munmap((void *) buffer, statistics.st_size); // Wrap up final material group materialRanges.push_back(MaterialRange(activeMaterialStart, (unsigned) originalIndices.size(), activeMaterial)); fillIndices(); }
bool rcMeshLoaderObj::loadContents(const char* contents) // TODO: PATCH { int bufSize = strlen(contents); char* buf = const_cast<char*>(contents); char* src = buf; //char* src = 0; char* srcEnd = buf + bufSize; char row[512]; int face[32]; float x,y,z; int nv; int vcap = 0; int tcap = 0; while (src < srcEnd) { // Parse one row row[0] = '\0'; src = parseRow(src, srcEnd, row, sizeof(row)/sizeof(char)); // Skip comments if (row[0] == '#') continue; if (row[0] == 'v' && row[1] != 'n' && row[1] != 't') { // Vertex pos sscanf(row+1, "%f %f %f", &x, &y, &z); addVertex(x, y, z, vcap); } if (row[0] == 'f') { // Faces nv = parseFace(row+1, face, 32, m_vertCount); for (int i = 2; i < nv; ++i) { const int a = face[0]; const int b = face[i-1]; const int c = face[i]; if (a < 0 || a >= m_vertCount || b < 0 || b >= m_vertCount || c < 0 || c >= m_vertCount) continue; addTriangle(a, b, c, tcap); } } } //delete [] buf; // Calculate normals. m_normals = new float[m_triCount*3]; for (int i = 0; i < m_triCount*3; i += 3) { const float* v0 = &m_verts[m_tris[i]*3]; const float* v1 = &m_verts[m_tris[i+1]*3]; const float* v2 = &m_verts[m_tris[i+2]*3]; float e0[3], e1[3]; for (int j = 0; j < 3; ++j) { e0[j] = v1[j] - v0[j]; e1[j] = v2[j] - v0[j]; } float* n = &m_normals[i]; n[0] = e0[1]*e1[2] - e0[2]*e1[1]; n[1] = e0[2]*e1[0] - e0[0]*e1[2]; n[2] = e0[0]*e1[1] - e0[1]*e1[0]; float d = sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]); if (d > 0) { d = 1.0f/d; n[0] *= d; n[1] *= d; n[2] *= d; } } return true; }
Model::Brush* MapParser::parseBrush(const BBox& worldBounds, Utility::ProgressIndicator* indicator) { Token token = m_tokenizer.nextToken(); if (token.type() == TokenType::Eof) return NULL; expect(TokenType::OBrace | TokenType::CBrace, token); if (token.type() == TokenType::CBrace) return NULL; const size_t firstLine = token.line(); Model::FaceList faces; while ((token = m_tokenizer.nextToken()).type() != TokenType::Eof) { switch (token.type()) { case TokenType::OParenthesis: { m_tokenizer.pushToken(token); Model::Face* face = parseFace(worldBounds); if (face != NULL) faces.push_back(face); break; } case TokenType::CBrace: { if (indicator != NULL) indicator->update(static_cast<int>(token.position())); Model::Brush* brush = new Model::Brush(worldBounds); // sort the faces by the weight of their plane normals like QBSP does Model::FaceList sortedFaces = faces; std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Plane::WeightOrder(true))); std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Plane::WeightOrder(false))); Model::FaceList::iterator faceIt = sortedFaces.begin(); Model::FaceList::iterator faceEnd = sortedFaces.end(); while (faceIt != faceEnd) { Model::Face* face = *faceIt++; if (!brush->addFace(face)) { m_console.warn("Skipping malformed brush at line %i", firstLine); delete brush; brush = NULL; break; } } // if something went wrong, we must delete all faces that have not been added to the brush yet if (faceIt != faceEnd) Utility::deleteAll(sortedFaces, faceIt); if (brush != NULL) { brush->setFilePosition(firstLine, token.line() - firstLine); if (!brush->closed()) m_console.warn("Non-closed brush at line %i", firstLine); } return brush; } default: { Utility::deleteAll(faces); throw MapParserException(token, TokenType::OParenthesis | TokenType::CParenthesis); } } } return NULL; }