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

  Program:   ParaView
  Module:    vtkPVTrackballRoll.cxx

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkPVTrackballRoll.h"

#include "vtkMath.h"
#include "vtkCamera.h"
#include "vtkObjectFactory.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkTransform.h"

vtkCxxRevisionMacro(vtkPVTrackballRoll, "1.5");
vtkStandardNewMacro(vtkPVTrackballRoll);

//-------------------------------------------------------------------------
vtkPVTrackballRoll::vtkPVTrackballRoll()
{
}

//-------------------------------------------------------------------------
vtkPVTrackballRoll::~vtkPVTrackballRoll()
{
}

//-------------------------------------------------------------------------
void vtkPVTrackballRoll::OnButtonDown(int x, int y, vtkRenderer *ren,
                                      vtkRenderWindowInteractor *)
{
  this->LastX = x;
  this->LastY = y;

  this->ComputeDisplayCenter(ren);
}


//-------------------------------------------------------------------------
void vtkPVTrackballRoll::OnButtonUp(int x, int y, vtkRenderer *,
                                    vtkRenderWindowInteractor *)
{
  this->LastX = x;
  this->LastY = y;
}

//-------------------------------------------------------------------------
void vtkPVTrackballRoll::OnMouseMove(int x, int y, vtkRenderer *ren,
                                     vtkRenderWindowInteractor *rwi)
{
  if (ren == NULL)
    {
    return;
    }

  vtkCamera *camera = ren->GetActiveCamera();
  vtkTransform *transform = vtkTransform::New();
  double axis[3];
  
  // compute view vector (rotation axis)
  double *pos = camera->GetPosition();
  double *fp = camera->GetFocalPoint();
  
  axis[0] = fp[0] - pos[0];
  axis[1] = fp[1] - pos[1];
  axis[2] = fp[2] - pos[2];
  
  // compute the angle of rotation
  // - first compute the two vectors (center to mouse)
  int x1, x2, y1, y2;
  x1 = this->LastX - (int)this->DisplayCenter[0];
  x2 = x - (int)this->DisplayCenter[0];
  y1 = this->LastY - (int)this->DisplayCenter[1];
  y2 = y - (int)this->DisplayCenter[1];
  
  // - compute cross product (only need z component)
  double zCross = x1*y2 - y1*x2;
  
  // - divide by madnitudes to get angle
  double angle = vtkMath::RadiansToDegrees() * zCross /
    (sqrt(static_cast<float>(x1*x1 + y1*y1)) *
     sqrt(static_cast<float>(x2*x2 + y2*y2)));
  
  // translate to center
  transform->Identity();
  transform->Translate(this->Center[0], this->Center[1], this->Center[2]);
  
  // roll
  transform->RotateWXYZ(angle, axis[0], axis[1], axis[2]);
  
  // translate back
  transform->Translate(-this->Center[0], -this->Center[1], -this->Center[2]);
  
  camera->ApplyTransform(transform);
  camera->OrthogonalizeViewUp();
  ren->ResetCameraClippingRange();
  
  rwi->Render();
  transform->Delete();

  this->LastX = x;
  this->LastY = y;
}

//-------------------------------------------------------------------------
void vtkPVTrackballRoll::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}






