Esempio n. 1
0
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;
}
		Shape *PhysicsEntityComponentTemplate::TrimeshInfo::create(Entity *entity)
		{
			Engine *engine = entity->getWorld()->getEngine();
			// Load trimesh data
			TrimeshData tridata;
			if (!tridata.init(engine->getDirectory() + "/Data/Graphics/" + file))
			{
				return 0;
			}
			// Create shape
			Trimesh *trimesh = new Trimesh;
			if (!trimesh->init(tridata, 0.0f, false))
			{
				delete trimesh;
				return 0;
			}
			return trimesh;
		}
Esempio n. 3
0
void SceneLoader::ImportMesh(Scene& scene, const aiMesh* const mesh) {
    Trimesh* trimesh = new Trimesh();
    for (uint32_t i = 0; i < mesh->mNumVertices; ++i) {
        aiVector3D v = mesh->mVertices[i];
        trimesh->AddVertex(glm::vec3(v[0], v[1], v[2]));
    }
    std::cout << "mNumVertices = " << mesh->mNumVertices << std::endl;
    if (NULL != mesh->mNormals) {
        for (uint32_t i = 0; i < mesh->mNumVertices; ++i) {
            aiVector3D n = mesh->mNormals[i];
            trimesh->AddNormal(glm::vec3(n[0], n[1], n[2]));
        }
    }
    std::cout << "mNumFaces = " << mesh->mNumFaces << std::endl;
    for (uint32_t i = 0; i < mesh->mNumFaces; ++i) {
        aiFace f = mesh->mFaces[i];
        if (3 == f.mNumIndices) {
            trimesh->AddFace(f.mIndices[0], f.mIndices[1], f.mIndices[2]);
        }
    }
    std::cout << "materials.size() = " << scene.material_list().materials.size()
              << std::endl;
    Material* mat = &scene.material_list().materials[mesh->mMaterialIndex];
    trimesh->set_material(mat);
    if (NULL == mesh->mNormals) {
        trimesh->GenNormals();
    }
    scene.AddSceneShape(static_cast<SceneShape*>(trimesh));
}
Esempio n. 4
0
TEST(RayTracerTest, TurbineMeshTest) {
  SceneLoader& loader = SceneLoader::GetInstance();
  std::string path = "../assets/blade.ply";
  std::string status = "";
  Scene scene;
  std::cout << "loading" << std::endl;
  bool success = loader.LoadScene(path, scene, status);
  EXPECT_TRUE(success);
  EXPECT_EQ("OK", status);
  std::cout << "done loading" << std::endl;
  int image_width = 1024;
  int image_height = 1024;
  glm::vec3 eye_pos = glm::vec3(-274.564f, -282.243f, 950.0f);
  glm::vec3 at_pos = glm::vec3(-274.564f, -282.243f, 254.327f);
  glm::vec3 up_dir = glm::vec3(0.0f, 1.0f, 0.0f);
  std::cout << "set camera" << std::endl;
  glm::mat4x4 look_at = LookAt(eye_pos, at_pos, up_dir);
  Camera camera(image_width, image_height, Orthographic(0.0f, 1.0f), look_at);
  std::cout << "camera set" << std::endl;

  Light point_light;
  glm::vec3 point_light_color = glm::vec3(0.4f, 0.4f, 0.4f);
  point_light.ka = point_light_color;
  point_light.kd = point_light_color;
  point_light.ks = point_light_color;
  point_light.ray = Ray(glm::vec3(0.0, -400.0, 400.0f), glm::vec3(0.0f));
  point_light.type = Light::kPoint;
  point_light.attenuation_coefficients = glm::vec3(0.25f, 0.003372407f,
      0.000045492f);

  Light directional_light;
  glm::vec3 directional_light_color = glm::vec3(0.4f, 0.4f, 0.4f);
  directional_light.ka = directional_light_color;
  directional_light.kd = directional_light_color;
  directional_light.ks = directional_light_color;
  directional_light.ray = Ray(glm::vec3(0.0f), glm::vec3(0.0f, -1.0f, -1.0f));
  directional_light.type = Light::kDirectional;

  scene.AddLight(point_light);
  scene.AddLight(directional_light);

  Trimesh* trimesh = static_cast<Trimesh*>(scene.scene_objects()[0]);
  OctreeType octree;
  std::cout << "Building octree" << std::endl;
  octree.Build(trimesh->faces());
  //octree.set_trace(true);
  //octree.Print(std::cout);
  std::cout << "Octree built.\n";
  std::cout << "bounds = " << octree.GetBounds() << " center = "
      << octree.GetBounds().GetCenter() << std::endl;
  trimesh->set_accelerator(&octree);
  Image image;
  image.Resize(image_width, image_height);
  RayTracer ray_tracer(&scene, &camera);
  ray_tracer.set_display_progress(!use_timing);
  ray_tracer.set_display_stats(!use_timing);
  ray_tracer.set_background_color(glm::vec3(0.05f, 0.05f, 0.05f));

  timeval t_start, t_finish;
  if (use_timing)
    gettimeofday(&t_start, NULL);
  std::cout << "Rendering..." << std::endl;
  ray_tracer.Render(image);
  if (use_timing) {
    gettimeofday(&t_finish, NULL);
    float sec = t_finish.tv_sec - t_start.tv_sec + t_finish.tv_usec / 1000000.0f
        - t_start.tv_usec / 1000000.0f;
    std::cout << "Render time:" << sec << std::endl;
  } else
    std::cout << "Done." << std::endl;

  ImageStorage& storage = ImageStorage::GetInstance();
  success = storage.WriteImage("blade_octree.jpg", image, status);
  EXPECT_TRUE(success);
  EXPECT_EQ("OK", status);
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
void parseInput(char cmd[LINE_SIZE], bool isCommand)
{
    std::vector<char*> v;

    char* chars_array = strtok(cmd, " ");
    while(chars_array)
    {
        v.push_back(chars_array);
        chars_array = strtok(NULL, " ");
    }
    float span;
    if(meshes.size() > 0)
    {
	    float diam = meshes.back()->get_diam();
	    float z = 1.0f + diam * 4.0f + perm_zoom + zoom;
	    float theta = 30.0f/2.0f;
	    float tang = tan(theta);
	    float opposite = tang * z;
	    span = -opposite;    	
    }
	int i;
	Trimesh* mesh;
	if(v.size() == 0)
		return;
	if(meshes.size() > 0)
		mesh = meshes.back();
	if(!strcmp(v[0], "L") & v.size() >= 2)
	{
		cout << "Loading file: " << v[1]  << endl;
		Trimesh* mesh = new Trimesh();

		if(loader->loadOBJ(v[1], mesh))
		{
			meshes.push_back(mesh);
			flushTransformations();
		}		
	}
	else if(!strcmp(v[0], "D"))
	{
		if(v.size() >= 2)
		{
			meshes.erase(meshes.begin() + atoi(v[1]));
			printFiles();
		}	
		else
			meshes.pop_back();
	}
	else if(!strcmp(v[0], "I"))
	{
		mesh->addTransformation(4.0f, 0.f, 0.f, 0.f, 0.f);
		flushTransformations();
	}
	else if(!strcmp(v[0], "T") && v.size() >= 4)
	{
		if(local_coords && false)
			mesh->addTransformation(1.0f, 0.f, span * atof(v[1]), -span * atof(v[2]), span * atof(v[3]));
		else
			mesh->addTransformation(1.0f, 0.f, atof(v[1]), -atof(v[2]), atof(v[3]));
	}
	else if(!strcmp(v[0], "S") && v.size() >= 4)
	{
		if(local_coords && false)
		{

			mesh->addTransformation(2.0f, 0.f, 
			 atof(v[1]) == 1.0f ? 1.0f : span * atof(v[1]),
			 atof(v[2]) == 1.0f ? 1.0f : span * atof(v[2]), 
			 atof(v[3]) == 1.0f ? 1.0f : span * atof(v[3]));
		}		
		else
			mesh->addTransformation(2.0f, 0.f, atof(v[1]), atof(v[2]), atof(v[3]));
	}
	else if(!strcmp(v[0], "R") && v.size() >= 5)
	{
		mesh->addTransformation(3.0f, atof(v[1]), atof(v[2]), atof(v[3]), atof(v[4]));
	}
	else if(!strcmp(v[0], "V"))
	{
		local_coords = true;
	}
	else if(!strcmp(v[0], "W"))
	{
		local_coords = false;
	}
	else if(!strcmp(v[0], "POINT"))
	{
		mode = POINTS;
	}
	else if(!strcmp(v[0], "WIRE"))
	{
		mode = LINES;
	}
	else if(!strcmp(v[0], "SOLID"))
	{
		mode = FACES;
		lighting_off = true;
	}
	else if(!strcmp(v[0], "SHADED"))
	{
		mode = FACES;
		lighting_off = false;
	}
	else if(!strcmp(v[0], "FNORMALS"))
	{
		fnormals = !fnormals;
	}
	else if(!strcmp(v[0], "VNORMALS"))
	{
		vnormals = !vnormals;
	}
	else if(!strcmp(v[0], "QUIT"))
	{
		exit(0);
	}
	else if(!strcmp(v[0], "ROTATOPOTATO"))
	{
		auto_rotate_enabled = !auto_rotate_enabled;
	}
	else if(!strcmp(v[0], "OBJECTS"))
	{
		printFiles();
	}
	else if(!strcmp(v[0], "SWITCH"))
	{
		if(v.size() >= 2)
		{
			int ind = atoi(v[1]);
			meshes.push_back(meshes[ind]);
			meshes.erase(meshes.begin() + ind);
			printFiles();
		}
	}
	else if(!strcmp(v[0], "DRAW"))
	{
		if(v.size() >= 2)
		{
			int ind = atoi(v[1]);
			if(meshes.size()-1 >= ind)
				meshes[ind]->draw = true;
			printFiles();
		}
	}
	if(isCommand)
		newCommand = false;
}
Esempio n. 7
0
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 );
    }
  }
}
Esempio n. 8
0
int main(int argc, char **argv) {
  bool wants_tree = false;
  bool wants_tokens = false;
  bool wants_timeout = false;
  bool wants_render = false;
  bool wants_quiet = false;
  bool is_flat = true;
  int timeout = 45;
  std::string out_path = "";
  GeometryMode::geometry_mode_t geometry_mode = GeometryMode::SURFACE;

  int optind = 1;
  for (; optind < argc && argv[optind][0] == '-'; ++optind) {
    std::string formal = argv[optind];

    if (formal == "--timeout") {
      wants_timeout = true;
      if (optind < argc - 1) {
        for (size_t i = 0; i < strlen(argv[optind + 1]); ++i) {
          if (!isdigit(argv[optind + 1][i])) {
            usage("Timeout must be positive integer.");
          }
        }
        timeout = atoi(argv[optind + 1]);
        ++optind;
      } else {
        usage("Timeout must be given.");
      }
    }

    else if (formal == "--tree") {
      wants_tree = true;
    }
    
    else if (formal == "--tokens") {
      wants_tokens = true;
    }

    else if (formal == "-r") {
      wants_render = true;
    }

    else if (formal == "-q") {
      wants_quiet = true;
    }

    else if (formal == "-o") {
      if (optind < argc - 1) {
        out_path = argv[optind + 1];
        ++optind;
      } else {
        usage("-o given, but no path specified.");
      }
    }

    else if (formal == "--shading") {
      if (optind < argc - 1) {
        std::string mode_label = argv[optind + 1];
        if (mode_label == "FLAT") {
          is_flat = true;
        } else if (mode_label == "SMOOTH") {
          is_flat = false;
        } else {
          std::stringstream ss;
          ss << "unknown shading mode \"" << mode_label << "\"";
          usage(ss.str());
        }
        ++optind;
      } else {
        usage("--shading given, but invalid mode.");
      }
    }

    else if (formal == "--geometry") {
      if (optind < argc - 1) {
        std::string mode_label = argv[optind + 1];
        if (mode_label == "SURFACE") {
          geometry_mode = GeometryMode::SURFACE;
        } else if (mode_label == "PATH") {
          geometry_mode = GeometryMode::PATH;
        } else if (mode_label == "NONE") {
          geometry_mode = GeometryMode::NONE;
        } else {
          std::stringstream ss;
          ss << "unknown geometry mode \"" << mode_label << "\"";
          usage(ss.str());
        }
        ++optind;
      } else {
        usage("--geometry given, but no path specified.");
      }
    }

    else {
      usage("unknown option: " + formal);
    }
  }

  if (optind >= argc) {
    usage("No input path specified.");
  }

  std::string in_path = argv[optind];
  ++optind;

  if (optind < argc) {
    usage("Stray parameters.");
  }

  std::string source = Utilities::Slurp(in_path);

  std::ifstream in(in_path);
  Lexer lexer(in);
  try {
    const std::vector<Token> &tokens = lexer.lex();

    if (wants_tokens) {
      for (std::vector<Token>::const_iterator i = tokens.begin(); i != tokens.end(); ++i) {
        std::cout << *i << std::endl;
      }
    }
    
    Parser parser(tokens, source);
    Co<ExpressionBlock> program = parser.program();

    if (wants_tree) {
      std::cout << program << std::endl;
    }

    if (!wants_quiet) {
      Environment env;
      env.prime();
      env.setGeometryMode(geometry_mode);
      srand(time(NULL));
      rand();

      if (wants_timeout) {
        env.setTimeout(timeout);
      }

      /* std::future<void> future = std::async(std::launch::async, [&program, &env] { */
        /* program->evaluate(env); */
      /* }); */
      /* future.get(); */

      program->evaluate(env);
      Trimesh *trimesh = env.getMesh();

      if (out_path.length() > 0) {
        if (geometry_mode == GeometryMode::PATH) {
          std::ofstream out(out_path.c_str());
          out << env.getPathsJSON();
          out.close();
        } else if (geometry_mode == GeometryMode::SURFACE) {

          if (is_flat) {
            trimesh->DisconnectFaces();
            trimesh->ComputeMeta(true);
          } else {
            td::Trimesh *sharped = madeup::MeshBoolean::compute_normals(*trimesh, 20);
            delete trimesh;
            trimesh = sharped;
            trimesh->ComputeMeta(false);
          }

          if (out_path.find_first_of('.') == std::string::npos ||
              out_path.find(".json") == out_path.length() - 5) {
            trimesh->WriteJSON(out_path);
          } else if (out_path.find(".stl") == out_path.length() - 4) {
            trimesh->WriteSTL(out_path);
          } else {
            trimesh->WriteObj(out_path);
          }

          if (trimesh->GetVertexCount() == 0) {
            std::cerr << "Uh oh. You either didn't visit any locations or didn't invoke a solidifier. I can't make any models without more information from you." << std::endl;
          }
        }

        if (wants_render) {
          std::string command = "runx /Users/johnch/checkouts/cj_graphics/build/projects/mesher/mesher.app -m " + out_path;
          system(command.c_str());
        }
      }
    }

  } catch (std::bad_alloc e) {
    std::cerr << "Whoa! I don't have enough memory for that." << std::endl;
    in.close();
    exit(1);
  } catch (td::MessagedException e) {
    std::cerr << e.GetMessage() << std::endl;
    in.close();
    exit(1);
  }
  in.close();

  return 0;
}
Esempio n. 9
0
void Parser::parseObj(string inputfile, Scene* scene, const Material& parent, TransformNode* transform){
  // Trimesh* tmesh = new Trimesh( scene, new Material(mat), transform);
  std::cout << inputfile << std::endl;
  std::vector<tinyobj::shape_t> shapes;
  std::vector<tinyobj::material_t> materials;
  
  std::string err;
  bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str());
  
  if (!err.empty()) { // `err` may contain warning message.
    std::cerr << err << std::endl;
  }
  
  if (!ret) {
    exit(1);
  }

  //Else successful now add the objects to the scene
  for(int i = 0; i < shapes.size(); i++){
    //Will only support one material per object
    // Get Materials
    Trimesh* tmesh;
    if(!shapes[i].mesh.material_ids.empty()){
      auto mtr = materials[shapes[i].mesh.material_ids[0]];
  // float ambient[3];
  // float diffuse[3];
  // float specular[3];
  // float transmittance[3];
  // float emission[3];
  // float shininess;
  // float ior;

      Vec3d ke(mtr.emission[0], mtr.emission[1], mtr.emission[2]     );
      Vec3d ka(mtr.ambient[0], mtr.ambient[1], mtr.ambient[2]      );
      Vec3d ks(mtr.specular[0], mtr.specular[1], mtr.specular[2]     );
      Vec3d kd(mtr.diffuse[0], mtr.diffuse[1], mtr.diffuse[2]      );
      // Vec3d kt(mtr.transmittance[0], mtr.transmittance[1], mtr.transmittance[2]);
      Vec3d kt(1.0 - mtr.dissolve, 1.0 - mtr.dissolve,1.0 -  mtr.dissolve);
      std::cout  << "Tr " << mtr.transmittance[0]<< " " << mtr.transmittance[1] << " " <<  mtr.transmittance[2] << " :d->: "<< mtr.dissolve << std::endl;
      Vec3d kr = Vec3d(0.0,0.0,0.0);
      // if(mtr.dissolve < 1.0) kr = ks;
      if(mtr.dissolve < 1.0) kr = Vec3d(0.2,0.2,0.2);

     tmesh = new Trimesh( scene, new Material(ke, ka, ks, kd, kr,kt, mtr.shininess, mtr.ior), transform);
    }else{
     std::cerr << "Note: OBJ file missing material" << std::endl;
     tmesh = new Trimesh( scene, new Material(parent), transform);
    }
    for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) {
    //First Add Vertices
      Vec3d vert(shapes[i].mesh.positions[3*v+0], shapes[i].mesh.positions[3*v+1], shapes[i].mesh.positions[3*v+2]);
      tmesh->addVertex(vert);
    }
    for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
    //Then Add Faces
      tmesh->addFace(shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2]);
    }
    tmesh->generateNormals();
    // tmesh->buildKdTree();
    scene->addBB( tmesh );


  }
}