void TriangulateTraverser::handlePrimitive( Primitive * p ) { if( !optimizationAllowed( p->getSharedPtr<Primitive>() ) ) { return; } DP_ASSERT( !m_triangulatedPrimitive ); PrimitiveType primitiveType = p->getPrimitiveType(); if ( ( primitiveType == PrimitiveType::QUAD_STRIP ) || ( primitiveType == PrimitiveType::QUADS ) ) { // create a new Primitive QuadStrip -> TriStrip or Quads -> Tris m_triangulatedPrimitive = Primitive::create( primitiveType == PrimitiveType::QUAD_STRIP ? PrimitiveType::TRIANGLE_STRIP : PrimitiveType::TRIANGLES ); m_triangulatedPrimitive->setName( p->getName() ); m_triangulatedPrimitive->setAnnotation( p->getAnnotation() ); m_triangulatedPrimitive->setHints( p->getHints() ); m_triangulatedPrimitive->setTraversalMask( p->getTraversalMask() ); m_triangulatedPrimitive->setInstanceCount( p->getInstanceCount() ); m_triangulatedPrimitive->setElementRange( p->getElementOffset(), p->getElementCount() ); m_triangulatedPrimitive->setInstanceCount( p->getInstanceCount() ); m_triangulatedPrimitive->setVertexAttributeSet( p->getVertexAttributeSet() ); m_triangulatedPrimitive->setIndexSet( p->getIndexSet() ); // from quad strip to tri strip is just copying the Primitive into a new tri strip; that is, we're alread done // otherwise... if ( primitiveType == PrimitiveType::QUADS ) { m_triangulatedPrimitive->makeIndexed(); vector<unsigned int> newIndices; convertQuadsToTriangles( IndexSet::ConstIterator<unsigned int>( m_triangulatedPrimitive->getIndexSet(), m_triangulatedPrimitive->getElementOffset() ) , m_triangulatedPrimitive->getElementCount(), m_triangulatedPrimitive->getVertexAttributeSet(), newIndices , m_triangulatedPrimitive->getIndexSet()->getPrimitiveRestartIndex() ); IndexSetSharedPtr triangulatedIndexSet = std::static_pointer_cast<IndexSet>(m_triangulatedPrimitive->getIndexSet()->clone()); triangulatedIndexSet->setData( &newIndices[0], dp::checked_cast<unsigned int>(newIndices.size()) ); triangulatedIndexSet->setPrimitiveRestartIndex( ~0 ); } } }
void Geometry::parseFile() { // open our given file path in read mode ("r"). // and text mode ("t") Stream input(mFilePath, "rt"); mFileName = input.getFileName(); std::vector<Vector3> tempVertices; std::vector<Vector3> tempNormals; std::vector<Vector3> tempTexCoords; std::vector<Vector4> tempColors; // we read the file line by line until we are at the end while(!input.eof()) { std::string curLine = input.readLine(); // we have an empty line or a comment (starts with #) if(curLine.compare("") == 0 || curLine[0] == '#') { continue; } Tokenizer tokenizer(curLine); tokenizer.tokenize(); if(tokenizer.getNumTokens() == 0) { continue; } std::vector<std::string> tokens = tokenizer.getTokens(); // vertices if(tokens[0].compare("v") == 0) { Vector3 curVertex; for(size_t i = 1; i < tokens.size(); ++i) { curVertex.elements[i - 1] = atof(tokens[i].c_str()); } tempVertices.push_back(curVertex); } // normals else if(tokens[0].compare("vn") == 0) { Vector3 curNormal; for(size_t i = 1; i < tokens.size(); ++i) { curNormal.elements[i - 1] = atof(tokens[i].c_str()); } tempNormals.push_back(curNormal); } // texture coordinates else if(tokens[0].compare("vt") == 0) { Vector3 curTexCoord; for(size_t i = 1; i < tokens.size(); ++i) { curTexCoord.elements[i - 1] = atof(tokens[i].c_str()); } tempTexCoords.push_back(curTexCoord); } // colors. this is an extension needed only for the assignments. the standard // obj file format does not have vertex colors else if(tokens[0].compare("vc") == 0) { Vector4 curColor; for(size_t i = 1; i < tokens.size(); ++i) { curColor.elements[i - 1] = atof(tokens[i].c_str()); } tempColors.push_back(curColor); } // faces. in case of quads we convert to two triangles else if(tokens[0].compare("f") == 0) { if(tokens.size() == 4) { mPrimitiveType = TRIANGLES; } else if(tokens.size() == 5) { mPrimitiveType = QUADS; } // no supported primitive type else { continue; } typedef enum { vertex = 0, texcoord = 1, normal = 2, color = 3 } facePointParam; // we loop over every vertex in the face for(size_t i = 1; i < tokens.size(); ++i) { facePointParam curParam = vertex; size_t numParams = std::count(tokens[i].begin(), tokens[i].end(), '/'); size_t lastDelimiterIndex = -1; std::string remainderString = tokens[i]; // we loop over the v/t/n/c construct part by part by reading until the first // occurence of /, converting the string to the index of the component, and then removing this // part of the string for(size_t j = 0; j < (numParams + 1); ++j) { size_t firstDelimiter = remainderString.find_first_of("/"); std::string curString = remainderString.substr(lastDelimiterIndex + 1, firstDelimiter); if(curString.compare("") != 0) { size_t index = atoi(curString.c_str()); switch (curParam) { case vertex: mVertices.push_back(tempVertices[index]); break; case texcoord: mTexCoords.push_back(tempTexCoords[index]); break; case normal: mNormals.push_back(tempNormals[index]); break; case color: mColors.push_back(tempColors[index]); break; default: break; } } remainderString = remainderString.substr(firstDelimiter + 1, remainderString.size() - firstDelimiter - 1); curParam = (facePointParam)(((uint32_t)curParam) + 1); } } } // everything else, we are not interested else { // not handeled } } convertQuadsToTriangles(); }