You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
570 lines
16 KiB
570 lines
16 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkCameraInterpolator.cxx,v $
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkCameraInterpolator.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkCamera.h"
|
|
#include "vtkTransform.h"
|
|
#include "vtkTupleInterpolator.h"
|
|
#include <vtkstd/list>
|
|
|
|
vtkCxxRevisionMacro(vtkCameraInterpolator, "$Revision: 1.5 $");
|
|
vtkStandardNewMacro(vtkCameraInterpolator);
|
|
|
|
// PIMPL STL encapsulation for list of cameras. This just keeps track of all
|
|
// the data the user specifies, which is later dumped into the interpolators.
|
|
struct vtkICamera
|
|
{
|
|
double Time; //Parameter t
|
|
double P[3]; //Position
|
|
double FP[3]; //Focal point
|
|
double VUP[3];//ViewUp
|
|
double CR[2]; //Clipping range
|
|
double VA[1]; //View angle
|
|
double PS[1]; //Parallel scale
|
|
|
|
vtkICamera()
|
|
{
|
|
this->Time = 0.0;
|
|
this->P[0] = this->P[1] = this->P[2] = 0.0;
|
|
this->FP[0] = this->FP[1] = this->FP[2] = 0.0;
|
|
this->VUP[0] = this->VUP[1] = this->VUP[2] = 0.0;
|
|
this->CR[0] = 1.0; this->CR[0] = 1000.0;
|
|
this->VA[0] = 30.0;
|
|
this->PS[0] = 1.0;
|
|
}
|
|
vtkICamera(double t, vtkCamera *camera)
|
|
{
|
|
this->Time = t;
|
|
if ( camera )
|
|
{
|
|
camera->GetPosition(this->P);
|
|
camera->GetFocalPoint(this->FP);
|
|
camera->GetViewUp(this->VUP);
|
|
camera->GetClippingRange(this->CR);
|
|
this->VA[0] = camera->GetViewAngle();
|
|
this->PS[0] = camera->GetParallelScale();
|
|
}
|
|
else
|
|
{
|
|
this->P[0] = this->P[1] = this->P[2] = 0.0;
|
|
this->FP[0] = this->FP[1] = this->FP[2] = 0.0;
|
|
this->VUP[0] = this->VUP[1] = this->VUP[2] = 0.0;
|
|
this->CR[0] = 1.0; this->CR[0] = 1000.0;
|
|
this->VA[0] = 30.0;
|
|
this->PS[0] = 1.0;
|
|
}
|
|
}
|
|
};
|
|
|
|
// The list is arranged in increasing order in T
|
|
class vtkCameraList : public vtkstd::list<vtkICamera> {};
|
|
typedef vtkCameraList::iterator CameraListIterator;
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkCameraInterpolator::vtkCameraInterpolator()
|
|
{
|
|
// Set up the interpolation
|
|
this->InterpolationType = INTERPOLATION_TYPE_SPLINE;
|
|
|
|
// Spline interpolation
|
|
this->PositionInterpolator = vtkTupleInterpolator::New();
|
|
this->FocalPointInterpolator = vtkTupleInterpolator::New();
|
|
this->ViewUpInterpolator = vtkTupleInterpolator::New();
|
|
this->ViewAngleInterpolator = vtkTupleInterpolator::New();
|
|
this->ParallelScaleInterpolator = vtkTupleInterpolator::New();
|
|
this->ClippingRangeInterpolator = vtkTupleInterpolator::New();
|
|
|
|
// Track the important camera parameters
|
|
this->CameraList = new vtkCameraList;
|
|
this->Initialized = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkCameraInterpolator::~vtkCameraInterpolator()
|
|
{
|
|
delete this->CameraList;
|
|
|
|
this->SetPositionInterpolator(NULL);
|
|
this->SetFocalPointInterpolator(NULL);
|
|
this->SetViewUpInterpolator(NULL);
|
|
this->SetViewAngleInterpolator(NULL);
|
|
this->SetParallelScaleInterpolator(NULL);
|
|
this->SetClippingRangeInterpolator(NULL);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
unsigned long vtkCameraInterpolator::GetMTime()
|
|
{
|
|
unsigned long mTime=this->Superclass::GetMTime();
|
|
unsigned long posMTime, fpMTime, vupMTime, vaMTime, psMTime, crMTime;
|
|
|
|
if ( this->PositionInterpolator )
|
|
{
|
|
posMTime = this->PositionInterpolator->GetMTime();
|
|
mTime = (posMTime > mTime ? posMTime : mTime);
|
|
}
|
|
if ( this->FocalPointInterpolator )
|
|
{
|
|
fpMTime = this->FocalPointInterpolator->GetMTime();
|
|
mTime = (fpMTime > mTime ? fpMTime : mTime);
|
|
}
|
|
if ( this->ViewUpInterpolator )
|
|
{
|
|
vupMTime = this->ViewUpInterpolator->GetMTime();
|
|
mTime = (vupMTime > mTime ? vupMTime : mTime);
|
|
}
|
|
if ( this->ViewAngleInterpolator )
|
|
{
|
|
vaMTime = this->ViewAngleInterpolator->GetMTime();
|
|
mTime = (vaMTime > mTime ? vaMTime : mTime);
|
|
}
|
|
if ( this->ParallelScaleInterpolator )
|
|
{
|
|
psMTime = this->ParallelScaleInterpolator->GetMTime();
|
|
mTime = (psMTime > mTime ? psMTime : mTime);
|
|
}
|
|
if ( this->ClippingRangeInterpolator )
|
|
{
|
|
crMTime = this->ClippingRangeInterpolator->GetMTime();
|
|
mTime = (crMTime > mTime ? crMTime : mTime);
|
|
}
|
|
|
|
return mTime;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkCameraInterpolator::GetNumberOfCameras()
|
|
{
|
|
return this->CameraList->size();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkCameraInterpolator::GetMinimumT()
|
|
{
|
|
if ( this->CameraList->empty() )
|
|
{
|
|
return -VTK_LARGE_FLOAT;
|
|
}
|
|
else
|
|
{
|
|
return this->CameraList->front().Time;
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkCameraInterpolator::GetMaximumT()
|
|
{
|
|
if ( this->CameraList->empty() )
|
|
{
|
|
return VTK_LARGE_FLOAT;
|
|
}
|
|
else
|
|
{
|
|
return this->CameraList->back().Time;
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::Initialize()
|
|
{
|
|
this->CameraList->clear();
|
|
this->Initialized = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::AddCamera(double t, vtkCamera *camera)
|
|
{
|
|
int size = this->CameraList->size();
|
|
|
|
// Check special cases: t at beginning or end of list
|
|
if ( size <= 0 || t < this->CameraList->front().Time )
|
|
{
|
|
this->CameraList->push_front(vtkICamera(t,camera));
|
|
return;
|
|
}
|
|
else if ( t > this->CameraList->back().Time )
|
|
{
|
|
this->CameraList->push_back(vtkICamera(t,camera));
|
|
return;
|
|
}
|
|
else if ( size == 1 && t == this->CameraList->back().Time )
|
|
{
|
|
this->CameraList->front() = vtkICamera(t,camera);
|
|
return;
|
|
}
|
|
|
|
// Okay, insert in sorted order
|
|
CameraListIterator iter = this->CameraList->begin();
|
|
CameraListIterator nextIter = ++(this->CameraList->begin());
|
|
for (int i=0; i < (size-1); i++, ++iter, ++nextIter)
|
|
{
|
|
if ( t == iter->Time )
|
|
{
|
|
(*iter) = vtkICamera(t,camera);
|
|
}
|
|
else if ( t > iter->Time && t < nextIter->Time )
|
|
{
|
|
this->CameraList->insert(nextIter, vtkICamera(t,camera));
|
|
}
|
|
}
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::RemoveCamera(double t)
|
|
{
|
|
if ( t < this->CameraList->front().Time ||
|
|
t > this->CameraList->back().Time )
|
|
{
|
|
return;
|
|
}
|
|
|
|
CameraListIterator iter = this->CameraList->begin();
|
|
for ( ; iter->Time != t && iter != this->CameraList->end(); ++iter )
|
|
{
|
|
}
|
|
if ( iter != this->CameraList->end() )
|
|
{
|
|
this->CameraList->erase(iter);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::SetPositionInterpolator(vtkTupleInterpolator *pi)
|
|
{
|
|
if ( this->PositionInterpolator != pi )
|
|
{
|
|
if ( this->PositionInterpolator != NULL )
|
|
{
|
|
this->PositionInterpolator->Delete();
|
|
}
|
|
this->PositionInterpolator = pi;
|
|
if ( this->PositionInterpolator != NULL )
|
|
{
|
|
this->PositionInterpolator->Register(this);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::SetFocalPointInterpolator(vtkTupleInterpolator *fpi)
|
|
{
|
|
if ( this->FocalPointInterpolator != fpi )
|
|
{
|
|
if ( this->FocalPointInterpolator != NULL )
|
|
{
|
|
this->FocalPointInterpolator->Delete();
|
|
}
|
|
this->FocalPointInterpolator = fpi;
|
|
if ( this->FocalPointInterpolator != NULL )
|
|
{
|
|
this->FocalPointInterpolator->Register(this);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::SetViewUpInterpolator(vtkTupleInterpolator *vupi)
|
|
{
|
|
if ( this->ViewUpInterpolator != vupi )
|
|
{
|
|
if ( this->ViewUpInterpolator != NULL )
|
|
{
|
|
this->ViewUpInterpolator->Delete();
|
|
}
|
|
this->ViewUpInterpolator = vupi;
|
|
if ( this->ViewUpInterpolator != NULL )
|
|
{
|
|
this->ViewUpInterpolator->Register(this);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::SetClippingRangeInterpolator(vtkTupleInterpolator *cri)
|
|
{
|
|
if ( this->ClippingRangeInterpolator != cri )
|
|
{
|
|
if ( this->ClippingRangeInterpolator != NULL )
|
|
{
|
|
this->ClippingRangeInterpolator->Delete();
|
|
}
|
|
this->ClippingRangeInterpolator = cri;
|
|
if ( this->ClippingRangeInterpolator != NULL )
|
|
{
|
|
this->ClippingRangeInterpolator->Register(this);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::SetParallelScaleInterpolator(vtkTupleInterpolator *psi)
|
|
{
|
|
if ( this->ParallelScaleInterpolator != psi )
|
|
{
|
|
if ( this->ParallelScaleInterpolator != NULL )
|
|
{
|
|
this->ParallelScaleInterpolator->Delete();
|
|
}
|
|
this->ParallelScaleInterpolator = psi;
|
|
if ( this->ParallelScaleInterpolator != NULL )
|
|
{
|
|
this->ParallelScaleInterpolator->Register(this);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::SetViewAngleInterpolator(vtkTupleInterpolator *vai)
|
|
{
|
|
if ( this->ViewAngleInterpolator != vai )
|
|
{
|
|
if ( this->ViewAngleInterpolator != NULL )
|
|
{
|
|
this->ViewAngleInterpolator->Delete();
|
|
}
|
|
this->ViewAngleInterpolator = vai;
|
|
if ( this->ViewAngleInterpolator != NULL )
|
|
{
|
|
this->ViewAngleInterpolator->Register(this);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::InitializeInterpolation()
|
|
{
|
|
if ( this->CameraList->empty() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set up the interpolators if we need to
|
|
if ( !this->Initialized || this->GetMTime() > this->InitializeTime )
|
|
{
|
|
if ( !this->PositionInterpolator )
|
|
{
|
|
this->PositionInterpolator = vtkTupleInterpolator::New();
|
|
}
|
|
if ( !this->FocalPointInterpolator )
|
|
{
|
|
this->FocalPointInterpolator = vtkTupleInterpolator::New();
|
|
}
|
|
if ( !this->ViewUpInterpolator )
|
|
{
|
|
this->ViewUpInterpolator = vtkTupleInterpolator::New();
|
|
}
|
|
if ( !this->ClippingRangeInterpolator )
|
|
{
|
|
this->ClippingRangeInterpolator = vtkTupleInterpolator::New();
|
|
}
|
|
if ( !this->ParallelScaleInterpolator )
|
|
{
|
|
this->ParallelScaleInterpolator = vtkTupleInterpolator::New();
|
|
}
|
|
if ( !this->ViewAngleInterpolator )
|
|
{
|
|
this->ViewAngleInterpolator = vtkTupleInterpolator::New();
|
|
}
|
|
|
|
this->PositionInterpolator->Initialize();
|
|
this->FocalPointInterpolator->Initialize();
|
|
this->ViewUpInterpolator->Initialize();
|
|
this->ClippingRangeInterpolator->Initialize();
|
|
this->ParallelScaleInterpolator->Initialize();
|
|
this->ViewAngleInterpolator->Initialize();
|
|
|
|
this->PositionInterpolator->SetNumberOfComponents(3);
|
|
this->FocalPointInterpolator->SetNumberOfComponents(3);
|
|
this->ViewUpInterpolator->SetNumberOfComponents(3);
|
|
this->ClippingRangeInterpolator->SetNumberOfComponents(2);
|
|
this->ParallelScaleInterpolator->SetNumberOfComponents(1);
|
|
this->ViewAngleInterpolator->SetNumberOfComponents(1);
|
|
|
|
if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR )
|
|
{
|
|
this->PositionInterpolator->SetInterpolationTypeToLinear();
|
|
this->FocalPointInterpolator->SetInterpolationTypeToLinear();
|
|
this->ViewUpInterpolator->SetInterpolationTypeToLinear();
|
|
this->ClippingRangeInterpolator->SetInterpolationTypeToLinear();
|
|
this->ParallelScaleInterpolator->SetInterpolationTypeToLinear();
|
|
this->ViewAngleInterpolator->SetInterpolationTypeToLinear();
|
|
}
|
|
else if ( this->InterpolationType == INTERPOLATION_TYPE_SPLINE )
|
|
{
|
|
this->PositionInterpolator->SetInterpolationTypeToSpline();
|
|
this->FocalPointInterpolator->SetInterpolationTypeToSpline();
|
|
this->ViewUpInterpolator->SetInterpolationTypeToSpline();
|
|
this->ClippingRangeInterpolator->SetInterpolationTypeToSpline();
|
|
this->ParallelScaleInterpolator->SetInterpolationTypeToSpline();
|
|
this->ViewAngleInterpolator->SetInterpolationTypeToSpline();
|
|
}
|
|
else
|
|
{
|
|
; //manual override, user manipulates interpolators directly
|
|
}
|
|
|
|
// Okay, now we can load the interpolators with data
|
|
CameraListIterator iter = this->CameraList->begin();
|
|
for ( ; iter != this->CameraList->end(); ++iter)
|
|
{
|
|
this->PositionInterpolator->AddTuple(iter->Time,iter->P);
|
|
this->FocalPointInterpolator->AddTuple(iter->Time,iter->FP);
|
|
this->ViewUpInterpolator->AddTuple(iter->Time,iter->VUP);
|
|
this->ClippingRangeInterpolator->AddTuple(iter->Time,iter->CR);
|
|
this->ViewAngleInterpolator->AddTuple(iter->Time,iter->VA);
|
|
this->ParallelScaleInterpolator->AddTuple(iter->Time,iter->PS);
|
|
}
|
|
|
|
this->Initialized = 1;
|
|
this->InitializeTime.Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::InterpolateCamera(double t, vtkCamera *camera)
|
|
{
|
|
if ( this->CameraList->empty() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Make sure the camera and this class are initialized properly
|
|
this->InitializeInterpolation();
|
|
|
|
// Evaluate the interpolators
|
|
if ( t < this->CameraList->front().Time )
|
|
{
|
|
t = this->CameraList->front().Time;
|
|
}
|
|
|
|
else if ( t > this->CameraList->back().Time )
|
|
{
|
|
t = this->CameraList->back().Time;
|
|
}
|
|
|
|
double P[3],FP[3],VUP[3],CR[2],VA[1],PS[1];
|
|
this->PositionInterpolator->InterpolateTuple(t,P);
|
|
this->FocalPointInterpolator->InterpolateTuple(t,FP);
|
|
this->ViewUpInterpolator->InterpolateTuple(t,VUP);
|
|
this->ClippingRangeInterpolator->InterpolateTuple(t,CR);
|
|
this->ViewAngleInterpolator->InterpolateTuple(t,VA);
|
|
this->ParallelScaleInterpolator->InterpolateTuple(t,PS);
|
|
|
|
camera->SetPosition(P);
|
|
camera->SetFocalPoint(FP);
|
|
camera->SetViewUp(VUP);
|
|
camera->SetClippingRange(CR);
|
|
camera->SetViewAngle(VA[0]);
|
|
camera->SetParallelScale(PS[0]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCameraInterpolator::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
|
|
os << indent << "There are " << this->GetNumberOfCameras()
|
|
<< " cameras to be interpolated\n";
|
|
|
|
os << indent << "Interpolation Type: ";
|
|
if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR )
|
|
{
|
|
os << "Linear\n";
|
|
}
|
|
else if ( this->InterpolationType == INTERPOLATION_TYPE_SPLINE )
|
|
{
|
|
os << "Spline\n";
|
|
}
|
|
else //if ( this->InterpolationType == INTERPOLATION_TYPE_MANUAL )
|
|
{
|
|
os << "Manual\n";
|
|
}
|
|
|
|
os << indent << "Position Interpolator: ";
|
|
if ( this->PositionInterpolator )
|
|
{
|
|
os << this->PositionInterpolator << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << "(null)\n";
|
|
}
|
|
|
|
os << indent << "Focal Point Interpolator: ";
|
|
if ( this->FocalPointInterpolator )
|
|
{
|
|
os << this->FocalPointInterpolator << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << "(null)\n";
|
|
}
|
|
|
|
os << indent << "View Up Interpolator: ";
|
|
if ( this->ViewUpInterpolator )
|
|
{
|
|
os << this->ViewUpInterpolator << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << "(null)\n";
|
|
}
|
|
|
|
os << indent << "Clipping Range Interpolator: ";
|
|
if ( this->ClippingRangeInterpolator )
|
|
{
|
|
os << this->ClippingRangeInterpolator << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << "(null)\n";
|
|
}
|
|
|
|
os << indent << "View Angle Interpolator: ";
|
|
if ( this->ViewAngleInterpolator )
|
|
{
|
|
os << this->ViewAngleInterpolator << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << "(null)\n";
|
|
}
|
|
|
|
os << indent << "Parallel Scale Interpolator: ";
|
|
if ( this->ParallelScaleInterpolator )
|
|
{
|
|
os << this->ParallelScaleInterpolator << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << "(null)\n";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|