bool test2()
{
	int threads = 2;

	int pvpW = 1024;
	int pvpH = 1024;
	float tnear = 1.0f;
	float fov = 30;

	worker wo[threads];

	wo[0].start();
	wo[1].start();

	wo[0].init(device, "left");
	wo[1].init(device, "right");

	wo[0].setViewPort(pvpW, pvpH);
	wo[1].setViewPort(pvpW, pvpH);

	for(int f=0; f<rM.getNumOctrees(); f++)
	{
		vmml::vector<3, int> startV = rM.getStartCoord();
		vmml::vector<3, int> endV = rM.getEndCoord();
		vmml::vector<4, float> origin(startV.x() + ((endV.x()-startV.x())/3.0f), rM.getMaxHeight(), 1.1f*endV.z(), 1.0f);

		vmml::matrix<4,4,float> positionM = vmml::matrix<4,4,float>::IDENTITY;
		positionM.set_translation(vmml::vector<3,float>(origin.x(), origin.y(), origin.z()));
		vmml::matrix<4,4,float> model = vmml::matrix<4,4,float>::IDENTITY;
		model = positionM * model;

		vmml::vector<4, float> up(0.0f, 1.0f, 0.0f, 0.0f);
		vmml::vector<4, float> right(1.0f, 0.0f, 0.0f, 0.0f);
		float ft = tan(fov*M_PI/180);
		vmml::vector<4, float>LB(-ft, -ft, -tnear, 1.0f); 	
		vmml::vector<4, float>LT(-ft, ft, -tnear, 1.0f); 	
		vmml::vector<4, float>RT(0.0f, ft, -tnear, 1.0f); 	
		vmml::vector<4, float>RB(0.0f, -ft, -tnear, 1.0f); 	
		vmml::vector<4, float>LB2(0.0f, -ft, -tnear, 1.0f); 	
		vmml::vector<4, float>LT2(0.0f, ft, -tnear, 1.0f); 	
		vmml::vector<4, float>RT2(ft, ft, -tnear, 1.0f); 	
		vmml::vector<4, float>RB2(ft, -ft, -tnear, 1.0f); 	
		LB = model*LB;
		LT = model*LT;
		RB = model*RB;
		RT = model*RT;
		LB2 = model*LB2;
		LT2 = model*LT2;
		RB2 = model*RB2;
		RT2 = model*RT2;
		float w = (RB.x() - LB.x())/(float)pvpW;
		float h = (LT.y() - LB.y())/(float)pvpH;
		float w2 = (RB2.x() - LB2.x())/(float)pvpW;
		float h2 = (LT2.y() - LB2.y())/(float)pvpH;
		std::cout<<"Camera position "<<origin<<std::endl;
		std::cout<<"Frustum left"<<std::endl;
		std::cout<<LB<<std::endl;
		std::cout<<LT<<std::endl;
		std::cout<<RB<<std::endl;
		std::cout<<RT<<std::endl;
		std::cout<<"Frustum right"<<std::endl;
		std::cout<<LB2<<std::endl;
		std::cout<<LT2<<std::endl;
		std::cout<<RB2<<std::endl;
		std::cout<<RT2<<std::endl;

		up = LT-LB;
		right = RB - LB;
		right.normalize();
		up.normalize();

		
		wo[0].startFrame(up, right, origin, LB, w, h);
		wo[1].startFrame(up, right, origin, LB2, w2, h2);

		wo[0].endFrame();
		wo[1].endFrame();

		if (f < rM.getNumOctrees()-1 && !rM.loadNext())
		{
			std::cerr<<"Error loading next isosurface"<<std::endl;
			return false;
		}
	}

	wo[0].end();
	wo[1].end();

	wo[0].join();
	wo[1].join();

	return true;
}
Zoltan_CrsGraph::NewTypeRef
Zoltan_CrsGraph::
operator()( OriginalTypeRef orig )
{
  origObj_ = &orig;

  int err;

  //Setup Load Balance Object
  float version;
  char * dummy = 0;
  Zoltan::LoadBalance LB( 0, &dummy, &version );
  err = LB.Create( dynamic_cast<const Epetra_MpiComm&>(orig.Comm()).Comm() );
  if( err == ZOLTAN_OK ) err = LB.Set_Param( "LB_METHOD", "GRAPH" );
#ifdef HAVE_LIBPARMETIS
  if( err == ZOLTAN_OK ) err = LB.Set_Param( "GRAPH_PACKAGE", "PARMETIS" );
  if( err == ZOLTAN_OK ) err = LB.Set_Param( "PARMETIS_METHOD", partitionMethod_ );
#endif

  //Setup Query Object
  CrsGraph_Transpose transposeTransform;
  Epetra_CrsGraph & TransGraph = transposeTransform( orig );
  ZoltanQuery Query( orig, &TransGraph );
  if( err == ZOLTAN_OK ) err = LB.Set_QueryObject( &Query );

  if( err != ZOLTAN_OK )
  { cout << "Setup of Zoltan Load Balancing Objects FAILED!\n"; exit(0); }

  //Generate Load Balance
  int changes;
  int num_gid_entries, num_lid_entries;
  int num_import;
  ZOLTAN_ID_PTR import_global_ids, import_local_ids;
  int * import_procs;
  int num_export;
  ZOLTAN_ID_PTR export_global_ids, export_local_ids;
  int * export_procs;

  orig.Comm().Barrier();
  err = LB.Balance( &changes,
                     &num_gid_entries, &num_lid_entries,
                     &num_import, &import_global_ids, &import_local_ids, &import_procs,
                     &num_export, &export_global_ids, &export_local_ids, &export_procs );
  LB.Evaluate( 1, 0, 0, 0, 0, 0, 0 );
  orig.Comm().Barrier();

  //Generate New Element List
  int numMyElements = orig.RowMap().NumMyElements();
  vector<int> elementList( numMyElements );
  orig.RowMap().MyGlobalElements( &elementList[0] );

  int newNumMyElements = numMyElements - num_export + num_import;
  vector<int> newElementList( newNumMyElements );

  set<int> gidSet;
  for( int i = 0; i < num_export; ++i )
    gidSet.insert( export_global_ids[i] );

  //Add unmoved indices to new list
  int loc = 0;
  for( int i = 0; i < numMyElements; ++i )
    if( !gidSet.count( elementList[i] ) )
      newElementList[loc++] = elementList[i];
  
  //Add imports to end of list
  for( int i = 0; i < num_import; ++i )
    newElementList[loc+i] = import_global_ids[i];

  //Free Zoltan Data
  if( err == ZOLTAN_OK )
    err = LB.Free_Data( &import_global_ids, &import_local_ids, &import_procs,
                         &export_global_ids, &export_local_ids, &export_procs );

  //Create Import Map
  NewRowMap_ = new Epetra_Map( orig.RowMap().NumGlobalElements(),
                                           newNumMyElements,
                                           &newElementList[0],
                                           orig.RowMap().IndexBase(),
                                           orig.RowMap().Comm() );

  //Create Importer
  Epetra_Import Importer( *NewRowMap_, orig.RowMap() );

  //Create New Graph
  Epetra_CrsGraph * NewGraph = new Epetra_CrsGraph( Copy, *NewRowMap_, 0 );
  NewGraph->Import( orig, Importer, Insert );
  NewGraph->FillComplete();

  Zoltan::LoadBalance LB2( 0, &dummy, &version );
  err = LB2.Create( dynamic_cast<const Epetra_MpiComm&>(orig.Comm()).Comm() );
  if( err == ZOLTAN_OK ) err = LB2.Set_Param( "LB_METHOD", "GRAPH" );
#ifdef HAVE_LIBPARMETIS
  if( err == ZOLTAN_OK ) err = LB2.Set_Param( "GRAPH_PACKAGE", "PARMETIS" );
  if( err == ZOLTAN_OK ) err = LB2.Set_Param( "PARMETIS_METHOD", partitionMethod_ );
#endif
  CrsGraph_Transpose transTrans;
  Epetra_CrsGraph & trans2 = transTrans( *NewGraph );
  ZoltanQuery query( *NewGraph, &trans2 );
  if( err == ZOLTAN_OK ) err = LB2.Set_QueryObject( &query );
  //err = LB2.Balance( &changes,
  //                   &num_gid_entries, &num_lid_entries,
  //                   &num_import, &import_global_ids, &import_local_ids, &import_procs,
  //                   &num_export, &export_global_ids, &export_local_ids, &export_procs );
  LB2.Evaluate( 1, 0, 0, 0, 0, 0, 0 );

  newObj_ = NewGraph;

  return *NewGraph;
}