Scene *readHeights(char* fn) { int width, height; unsigned char *height_map; height_map = readBMP(fn, width, height); if (!height_map) { fl_alert("Error loading height map\n"); return false; } Scene * ret = new Scene(); //TODO: customize mat Material * mat = new Material(); mat->kd = vec3f(1.0, 1.0, 1.0); //extract the points Trimesh * trimesh = new Trimesh(ret, mat, &ret->transformRoot); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int pos = y * width + x; unsigned char pixel[3]; memcpy(pixel, height_map + pos * 3, 3); double height = double(pixel[0] + pixel[1] + pixel[2]) / 3 / 128; vec3f point(x, y, height); trimesh->addVertex(point); if (x > 0 && y > 0) { //link the points trimesh->addFace(pos, pos - 1, pos - 1 - width); trimesh->addFace(pos, pos - 1 - width, pos - width); } } } char *error; if (error = trimesh->doubleCheck()) throw ParseError(error); //add a trimesh ret->add(trimesh); //add a pointlight PointLight* point_light = new PointLight(ret, vec3f(width, height, 10), vec3f(1.0, 1.0, 1.0)); ret->add(point_light); //set the camerea //TODO: calculate the correct viewing distance; vec3f map_center((double)width / 2 - 0.5, (double)height / 2 - 0.5, 0.5); double camera_distance = (double)width + 3.0; vec3f camera_pos(0, -camera_distance, 2 * camera_distance); camera_pos += map_center; ret->getCamera()->setEye(camera_pos); ret->getCamera()->setLook((map_center - camera_pos).normalize(), vec3f(0, 0, 1).normalize()); return ret; }
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 ); } } }