/*==================================================================

  Program:   View Generation Toolkit
  Module:    viewgen.cxx
  Language:  C++
  Date:      2002/05/27
  Version:   1.0

===================================================================*/

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtk3DSImporter.h"
#include "vtkLight.h"
#include "vtkRenderLargeImage.h"
#include "vtkTIFFWriter.h"
#include "vtkImageData.h"
#include "vtkProperty.h"
#include <math.h>
#include <stdio.h>
#include "viewgen.h"


CViewGenerator::CViewGenerator(const char* f)
{
  // Create the graphics structure. The renderer renders into the 
  // render window. 
  Renderer = vtkRenderer::New();
  RenderWindow = vtkRenderWindow::New();
  RenderWindow->AddRenderer(Renderer);
  IRender = vtkRenderWindowInteractor::New();
  IRender->SetRenderWindow(RenderWindow);

  // Set the default background and size
  //
  SetBackground(1, 1, 1);
  
  Width = 30; Height = 30; Magnification = 10;
  RenderWindow->SetSize(Width, Height);

  // Import 3D Studio Max file
  //
  Importer = vtk3DSImporter::New();
  Importer->SetRenderWindow(RenderWindow);
  Importer->SetFileName(f);
  Importer->ComputeNormalsOn();
  Importer->Read();
}

CViewGenerator::~CViewGenerator()
{
  // Exiting from here, we have to delete all the instances that
  // have been created.
  Importer->Delete();
  Renderer->Delete();
  RenderWindow->Delete();
  IRender->Delete();
}

void CViewGenerator::RemoveAllLights()
{
  Renderer->GetLights()->RemoveAllItems();
}

void CViewGenerator::SetModelColor(float r, float g, float b)
{
}

void CViewGenerator::SetModelAmbient(float p)
{
}

void CViewGenerator::SetModelDiffuse(float p)
{
}

void CViewGenerator::SetModelSpecular(float p)
{
}

void CViewGenerator::SetModelOpacity(float p)
{
}

void CViewGenerator::SetModelAmbientColor(float r, float g, float b)
{
}

void CViewGenerator::SetModelDiffuseColor(float r, float g, float b)
{
}

void CViewGenerator::SetModelSpecularColor(float r, float g, float b)
{
}

void CViewGenerator::SetModelEdgeVisibility(bool ev)
{
}

void CViewGenerator::SetModelEdgeColor(float r, float g, float b)
{
}

void CViewGenerator::SetupSilhouetteRendering()
{
    RemoveAllLights();
    SetupLight(0,0,0,0);
    
    vtkProperty* property = vtkProperty::New();

    property->SetColor(0,0,0);
    property->SetAmbient(0);
    property->SetDiffuse(0);
    property->SetSpecular(0);
    property->SetOpacity(1.0);
    property->SetAmbientColor(0,0,0);
    property->SetDiffuseColor(0,0,0);
    property->SetSpecularColor(0,0,0);
    property->EdgeVisibilityOn();
    property->SetEdgeColor(0,0,0);

    Renderer->GetActors()->ApplyProperties(property);
}

void CViewGenerator::Initialize()
{
  float bbox[6]; 

  // Calculate the bounding radius
  Renderer->ComputeVisiblePropBounds(bbox);
    
  origin[0] = (bbox[0]+bbox[1])/2;
  origin[1] = (bbox[2]+bbox[3])/2;
  origin[2] = (bbox[4]+bbox[5])/2;

  bbox[0] = (bbox[0]-bbox[1]);
  bbox[0] = bbox[0]*bbox[0];
  bbox[2] = (bbox[2]-bbox[3]);
  bbox[2] = bbox[2]*bbox[2];
  bbox[4] = (bbox[4]-bbox[5]);
  bbox[4] = bbox[4]*bbox[4];
  radius = sqrt(bbox[0] + bbox[2] + bbox[4])*2.1;
}

vtkLight* CViewGenerator::SetupLight(float r, float g, float b, float i)
{
  vtkLight* light;

  // Set the light to black
  light = vtkLight::New();
  light->SetColor(r,g,b);
  light->SetIntensity(i);
  Renderer->AddLight(light);
  
  return light;
}

vtkCamera* CViewGenerator::SetupCamera()
{
 return Renderer->GetActiveCamera();
}

void CViewGenerator::SetBackground(float r, float g, float b)
{
  Renderer->SetBackground(r, g, b);
}

void CViewGenerator::SetAmbientColor(float r, float g, float b)
{
  Renderer->SetAmbient(r,g,b);
}

void CViewGenerator::SetView(float phi, float theta)
{
    float pos[3];

    pos[0] = radius*sin(phi*degtorad)*cos(theta*degtorad) + origin[0];
    pos[1] = radius*sin(phi*degtorad)*sin(theta*degtorad) + origin[1];
    pos[2] = radius*cos(phi*degtorad) + origin[2];

    Renderer->GetActiveCamera()->SetFocalPoint(origin);
    Renderer->GetActiveCamera()->SetPosition(pos);
    Renderer->GetActiveCamera()->SetClippingRange(radius/10,radius*500);
}

vtkImageData* CViewGenerator::RenderCurrentView()
{
  vtkImageData* imgdata = vtkImageData::New();
  vtkRenderLargeImage *renderLarge = vtkRenderLargeImage::New();

  renderLarge->SetInput(Renderer);
  renderLarge->SetMagnification(Magnification);
  renderLarge->Update(); 
  imgdata->PrepareForNewData();
  imgdata->DeepCopy(renderLarge->GetOutput());
  renderLarge->Delete();

  return imgdata;    
}

vtkImageData* CViewGenerator::RenderView(float phi, float theta)
{
  SetView(phi, theta);
  return RenderCurrentView();
}

void CViewGenerator::WriteToTIFF(vtkImageData* data, const char* imgname)
{
  vtkTIFFWriter* writer = vtkTIFFWriter::New();
  writer->SetInput(data);
  writer->SetFileName(imgname);
  writer->Write();
  writer->Delete();    
}

void CViewGenerator::WriteViewToTIFF(float phi, float theta, const char* imgname)
{
  vtkImageData* data = RenderView(phi, theta);
  WriteToTIFF(data, imgname);
  data->Delete();
}

void CViewGenerator::SetMagnification(int m)
{
  Magnification = m;
}

void CViewGenerator::SetSize(int w, int h)
{
  Width = w; Height = h;
  RenderWindow->SetSize(w, h);
}


