#include "vtkSmartPointer.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkProperty.h"
#include "vtkCamera.h"


#include "vtkUnstructuredGrid.h"
#include "vtkUnstructuredGridReader.h"

#include "vtkFloatArray.h"
#include "vtkPointData.h"

#include "vtkProjectedTetrahedraMapper.h"

#include "vtkColorTransferFunction.h"
#include "vtkPiecewiseFunction.h"
#include "vtkVolumeProperty.h"
#include "vtkVolume.h"

#include "vtkWindowToImageFilter.h"
#include "vtkTIFFWriter.h"

#include "vtkWin32RenderWindowInteractor.h"
#include "vtkWin32OpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"


int main()
{
	std::string file_name_mesh_in = "mesh.vtk";
	std::string file_name_img_out = "renderWindow.tif";

	vtkSmartPointer<vtkUnstructuredGridReader> reader = vtkSmartPointer<vtkUnstructuredGridReader>::New();
	reader->SetFileName(file_name_mesh_in.c_str());
	reader->Update();

	vtkSmartPointer<vtkFloatArray> scalars = vtkSmartPointer<vtkFloatArray>::New();

	for (int scalar_index = 0; scalar_index < reader->GetOutput()->GetNumberOfPoints(); scalar_index++)
		scalars->InsertTuple1(scalar_index, 128.0);

	vtkSmartPointer<vtkUnstructuredGrid> theGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
	theGrid->DeepCopy(reader->GetOutput());
	theGrid->GetPointData()->SetScalars(scalars);

	vtkSmartPointer<vtkProjectedTetrahedraMapper> volumeMapper = vtkSmartPointer<vtkProjectedTetrahedraMapper>::New();
	volumeMapper->SetInputData(theGrid);
	volumeMapper->Update();

	vtkSmartPointer<vtkColorTransferFunction> colorTF = vtkSmartPointer<vtkColorTransferFunction>::New();
	colorTF->AddRGBPoint(128.0, 0.0, 0.0, 0.0);

	vtkSmartPointer<vtkPiecewiseFunction> opacityTF = vtkSmartPointer<vtkPiecewiseFunction>::New();
	opacityTF->AddPoint(128.0, 0.5);

	vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
	volumeProperty->SetColor(colorTF);
	volumeProperty->SetScalarOpacity(opacityTF);
	volumeProperty->ShadeOff();
	volumeProperty->SetInterpolationTypeToLinear();

	vtkSmartPointer<vtkVolume> theVolume = vtkSmartPointer<vtkVolume>::New();
	theVolume->SetMapper(volumeMapper);
	theVolume->SetProperty(volumeProperty);

	/////////////////////////////////////////////////////////////////////////////////////////////////////
	
	vtkSmartPointer<vtkWin32OpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkWin32OpenGLRenderWindow>::New();
	vtkSmartPointer<vtkOpenGLRenderer> renderer = vtkSmartPointer<vtkOpenGLRenderer>::New();
	vtkSmartPointer<vtkWin32RenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkWin32RenderWindowInteractor>::New();

	vtkCamera* camera = renderer->MakeCamera();

	renderer->SetBackground(1.0, 1.0, 1.0);
	renderWindow->AddRenderer(renderer);
	renderWindowInteractor->SetRenderWindow(renderWindow);
    
	renderer->SetActiveCamera(camera);

	renderWindow->OffScreenRenderingOn();
	renderWindow->SetSize(600, 600);
	
	renderWindow->Start();

	//renderWindow->SetupPixelFormatPaletteAndContext((HDC)renderWindow->GetGenericContext(), PFD_SUPPORT_OPENGL |
	//  PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER,
	//	renderWindow->GetDebug(), 32, 32);

	renderer->AddViewProp(theVolume);

	renderer->ResetCamera();
	
	renderWindow->Render();


	//vtkSmartPointer<vtkRenderLargeImage> renderLarge = vtkSmartPointer<vtkRenderLargeImage>::New();
	//renderLarge->SetInput(renderer);
	//renderLarge->SetMagnification(1);
	//renderLarge->Update();

	vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
	windowToImageFilter->SetInput(renderWindow);
	windowToImageFilter->SetMagnification(1);
	windowToImageFilter->Update();

	vtkSmartPointer<vtkTIFFWriter> writer = vtkSmartPointer<vtkTIFFWriter>::New();
	writer->SetFileName(file_name_img_out.c_str());
    //writer->SetInputConnection(renderLarge->GetOutputPort());
	writer->SetInputConnection(windowToImageFilter->GetOutputPort());
	writer->SetCompressionToNoCompression();
	writer->Write();

	// This starts the event loop and as a side effect causes an initial render.
	renderWindowInteractor->Start();

  return 0;
}
