static void processTrimesh( string name, Obj *child, Scene *scene, const mmap& materials, TransformNode *transform ) { Material *mat; if( hasField( child, "material" ) ) mat = getMaterial( getField( child, "material" ), materials ); else mat = new Material(); Trimesh *tmesh = new Trimesh( scene, mat, transform); const mytuple &points = getField( child, "points" )->getTuple(); for( mytuple::const_iterator pi = points.begin(); pi != points.end(); ++pi ) tmesh->addVertex( tupleToVec( *pi ) ); const mytuple &faces = getField( child, "faces" )->getTuple(); for( mytuple::const_iterator fi = faces.begin(); fi != faces.end(); ++fi ) { const mytuple &pointids = (*fi)->getTuple(); // triangulate here and now. assume the poly is // concave and we can triangulate using an arbitrary fan if( pointids.size() < 3 ) throw ParseError( "Faces must have at least 3 vertices." ); mytuple::const_iterator i = pointids.begin(); int a = (int) (*i++)->getScalar(); int b = (int) (*i++)->getScalar(); while( i != pointids.end() ) { int c = (int) (*i++)->getScalar(); if( !tmesh->addFace(a,b,c) ) throw ParseError( "Bad face in trimesh." ); b = c; } } bool generateNormals = false; maybeExtractField( child, "gennormals", generateNormals ); if( generateNormals ) tmesh->generateNormals(); if( hasField( child, "materials" ) ) { const mytuple &mats = getField( child, "materials" )->getTuple(); for( mytuple::const_iterator mi = mats.begin(); mi != mats.end(); ++mi ) tmesh->addMaterial( getMaterial( *mi, materials ) ); } if( hasField( child, "normals" ) ) { const mytuple &norms = getField( child, "normals" )->getTuple(); for( mytuple::const_iterator ni = norms.begin(); ni != norms.end(); ++ni ) tmesh->addNormal( tupleToVec( *ni ) ); } char *error; if( error = tmesh->doubleCheck() ) throw ParseError( error ); scene->add(tmesh); }
void Parser::parseTrimesh(Scene* scene, TransformNode* transform, const Material& mat) { Trimesh* tmesh = new Trimesh( scene, new Material(mat), transform); _tokenizer.Read( TRIMESH ); _tokenizer.Read( LBRACE ); bool generateNormals( true ); list<Vec3d> faces; char* error; for( ;; ) { const Token* t = _tokenizer.Peek(); switch( t->kind() ) { case GENNORMALS: _tokenizer.Read( GENNORMALS ); _tokenizer.Read( SEMICOLON ); generateNormals = true; break; case MATERIAL: tmesh->setMaterial( parseMaterialExpression( scene, mat ) ); break; case NAME: parseIdentExpression(); break; case MATERIALS: _tokenizer.Read( MATERIALS ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { tmesh->addMaterial( parseMaterial( scene, tmesh->getMaterial() ) ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); tmesh->addMaterial( parseMaterial( scene, tmesh->getMaterial() ) ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case NORMALS: _tokenizer.Read( NORMALS ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { tmesh->addNormal( parseVec3d() ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); tmesh->addNormal( parseVec3d() ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case FACES: _tokenizer.Read( FACES ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { parseFaces( faces ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); parseFaces( faces ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case POLYPOINTS: _tokenizer.Read( POLYPOINTS ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { tmesh->addVertex( parseVec3d() ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); tmesh->addVertex( parseVec3d() ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case RBRACE: { _tokenizer.Read( RBRACE ); // Now add all the faces into the trimesh, since hopefully // the vertices have been parsed out for( list<Vec3d>::const_iterator vitr = faces.begin(); vitr != faces.end(); vitr++ ) { if( !tmesh->addFace( (*vitr)[0], (*vitr)[1], (*vitr)[2] ) ) { ostringstream oss; oss << "Bad face in trimesh: (" << (*vitr)[0] << ", " << (*vitr)[1] << ", " << (*vitr)[2] << ")"; throw ParserException( oss.str() ); } } if( generateNormals ) tmesh->generateNormals(); if( error = tmesh->doubleCheck() ) throw ParserException( error ); scene->add( tmesh ); return; } default: throw SyntaxErrorException( "Expected: trimesh attributes", _tokenizer ); } } }