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.
391 lines
11 KiB
391 lines
11 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkRenderWindowInteractor.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 "vtkRenderWindowInteractor.h"
|
|
|
|
#include "vtkCamera.h"
|
|
#include "vtkCommand.h"
|
|
#include "vtkGraphicsFactory.h"
|
|
#include "vtkInteractorStyleSwitch.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkPropPicker.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkRendererCollection.h"
|
|
#include "vtkDebugLeaks.h"
|
|
|
|
vtkCxxRevisionMacro(vtkRenderWindowInteractor, "$Revision: 1.108 $");
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Needed when we don't use the vtkStandardNewMacro.
|
|
vtkInstantiatorNewMacro(vtkRenderWindowInteractor);
|
|
//----------------------------------------------------------------------------
|
|
|
|
vtkCxxSetObjectMacro(vtkRenderWindowInteractor,Picker,vtkAbstractPicker);
|
|
|
|
// Construct object so that light follows camera motion.
|
|
vtkRenderWindowInteractor::vtkRenderWindowInteractor()
|
|
{
|
|
this->RenderWindow = NULL;
|
|
this->InteractorStyle = NULL;
|
|
this->SetInteractorStyle(vtkInteractorStyleSwitch::New());
|
|
this->InteractorStyle->Delete();
|
|
|
|
this->LightFollowCamera = 1;
|
|
this->Initialized = 0;
|
|
this->Enabled = 0;
|
|
this->DesiredUpdateRate = 15;
|
|
// default limit is 3 hours per frame
|
|
this->StillUpdateRate = 0.0001;
|
|
|
|
this->Picker = this->CreateDefaultPicker();
|
|
this->Picker->Register(this);
|
|
this->Picker->Delete();
|
|
|
|
this->EventPosition[0] = this->LastEventPosition[0] = 0;
|
|
this->EventPosition[1] = this->LastEventPosition[1] = 0;
|
|
|
|
this->EventSize[0] = 0;
|
|
this->EventSize[1] = 0;
|
|
|
|
this->Size[0] = 0;
|
|
this->Size[1] = 0;
|
|
|
|
this->NumberOfFlyFrames = 15;
|
|
this->Dolly = 0.30;
|
|
|
|
this->ControlKey = 0;
|
|
this->ShiftKey = 0;
|
|
this->KeyCode = 0;
|
|
this->RepeatCount = 0;
|
|
this->KeySym = 0;
|
|
}
|
|
|
|
vtkRenderWindowInteractor::~vtkRenderWindowInteractor()
|
|
{
|
|
if (this->InteractorStyle != NULL)
|
|
{
|
|
this->InteractorStyle->UnRegister(this);
|
|
}
|
|
if ( this->Picker)
|
|
{
|
|
this->Picker->UnRegister(this);
|
|
}
|
|
if ( this->KeySym )
|
|
{
|
|
delete [] this->KeySym;
|
|
}
|
|
}
|
|
|
|
vtkRenderWindowInteractor *vtkRenderWindowInteractor::New()
|
|
{
|
|
// First try to create the object from the vtkObjectFactory
|
|
vtkObject* ret =
|
|
vtkGraphicsFactory::CreateInstance("vtkRenderWindowInteractor");
|
|
if ( ret )
|
|
{
|
|
return (vtkRenderWindowInteractor *)ret;
|
|
}
|
|
#ifdef VTK_DEBUG_LEAKS
|
|
vtkDebugLeaks::ConstructClass("vtkRenderWindowInteractor");
|
|
#endif
|
|
return new vtkRenderWindowInteractor;
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::Render()
|
|
{
|
|
if (this->RenderWindow && this->Enabled)
|
|
{
|
|
this->RenderWindow->Render();
|
|
}
|
|
// outside the above test so that third-party code can redirect
|
|
// the render to the appropriate class
|
|
this->InvokeEvent(vtkCommand::RenderEvent, NULL);
|
|
}
|
|
|
|
// treat renderWindow and interactor as one object.
|
|
// it might be easier if the GetReference count method were redefined.
|
|
void vtkRenderWindowInteractor::UnRegister(vtkObjectBase *o)
|
|
{
|
|
if (this->RenderWindow && this->RenderWindow->GetInteractor() == this &&
|
|
this->RenderWindow != o)
|
|
{
|
|
if (this->GetReferenceCount()+this->RenderWindow->GetReferenceCount() == 3)
|
|
{
|
|
this->RenderWindow->SetInteractor(NULL);
|
|
this->SetRenderWindow(NULL);
|
|
}
|
|
}
|
|
|
|
this->vtkObject::UnRegister(o);
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::SetRenderWindow(vtkRenderWindow *aren)
|
|
{
|
|
if (this->RenderWindow != aren)
|
|
{
|
|
// to avoid destructor recursion
|
|
vtkRenderWindow *temp = this->RenderWindow;
|
|
this->RenderWindow = aren;
|
|
if (temp != NULL)
|
|
{
|
|
temp->UnRegister(this);
|
|
}
|
|
if (this->RenderWindow != NULL)
|
|
{
|
|
this->RenderWindow->Register(this);
|
|
if (this->RenderWindow->GetInteractor() != this)
|
|
{
|
|
this->RenderWindow->SetInteractor(this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::SetInteractorStyle(vtkInteractorObserver *style)
|
|
{
|
|
if (this->InteractorStyle != style)
|
|
{
|
|
// to avoid destructor recursion
|
|
vtkInteractorObserver *temp = this->InteractorStyle;
|
|
this->InteractorStyle = style;
|
|
if (temp != NULL)
|
|
{
|
|
temp->SetInteractor(0);
|
|
temp->UnRegister(this);
|
|
}
|
|
if (this->InteractorStyle != NULL)
|
|
{
|
|
this->InteractorStyle->Register(this);
|
|
if (this->InteractorStyle->GetInteractor() != this)
|
|
{
|
|
this->InteractorStyle->SetInteractor(this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::UpdateSize(int x,int y)
|
|
{
|
|
// if the size changed send this on to the RenderWindow
|
|
if ((x != this->Size[0])||(y != this->Size[1]))
|
|
{
|
|
this->Size[0] = this->EventSize[0] = x;
|
|
this->Size[1] = this->EventSize[1] = y;
|
|
this->RenderWindow->SetSize(x,y);
|
|
}
|
|
}
|
|
|
|
// Creates an instance of vtkPropPicker by default
|
|
vtkAbstractPropPicker *vtkRenderWindowInteractor::CreateDefaultPicker()
|
|
{
|
|
return vtkPropPicker::New();
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::ExitCallback()
|
|
{
|
|
if (this->HasObserver(vtkCommand::ExitEvent))
|
|
{
|
|
this->InvokeEvent(vtkCommand::ExitEvent,NULL);
|
|
}
|
|
else
|
|
{
|
|
this->TerminateApp();
|
|
}
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::UserCallback()
|
|
{
|
|
this->InvokeEvent(vtkCommand::UserEvent,NULL);
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::StartPickCallback()
|
|
{
|
|
this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::EndPickCallback()
|
|
{
|
|
this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::FlyTo(vtkRenderer *ren, double x, double y, double z)
|
|
{
|
|
double flyFrom[3], flyTo[3];
|
|
double d[3], focalPt[3];
|
|
int i, j;
|
|
|
|
flyTo[0]=x; flyTo[1]=y; flyTo[2]=z;
|
|
ren->GetActiveCamera()->GetFocalPoint(flyFrom);
|
|
for (i=0; i<3; i++)
|
|
{
|
|
d[i] = flyTo[i] - flyFrom[i];
|
|
}
|
|
double distance = vtkMath::Normalize(d);
|
|
double delta = distance/this->NumberOfFlyFrames;
|
|
|
|
for (i=1; i<=NumberOfFlyFrames; i++)
|
|
{
|
|
for (j=0; j<3; j++)
|
|
{
|
|
focalPt[j] = flyFrom[j] + d[j]*i*delta;
|
|
}
|
|
ren->GetActiveCamera()->SetFocalPoint(focalPt);
|
|
ren->GetActiveCamera()->Dolly(this->Dolly/this->NumberOfFlyFrames + 1.0);
|
|
ren->GetActiveCamera()->OrthogonalizeViewUp();
|
|
ren->ResetCameraClippingRange();
|
|
this->Render();
|
|
}
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::FlyToImage(vtkRenderer *ren, double x, double y)
|
|
{
|
|
double flyFrom[3], flyTo[3];
|
|
double d[3], focalPt[3], position[3], positionFrom[3];
|
|
int i, j;
|
|
|
|
flyTo[0]=x; flyTo[1]=y;
|
|
ren->GetActiveCamera()->GetFocalPoint(flyFrom); flyTo[2] = flyFrom[2];
|
|
ren->GetActiveCamera()->GetPosition(positionFrom);
|
|
for (i=0; i<2; i++)
|
|
{
|
|
d[i] = flyTo[i] - flyFrom[i];
|
|
}
|
|
d[2] = 0.0;
|
|
double distance = vtkMath::Normalize(d);
|
|
double delta = distance/this->NumberOfFlyFrames;
|
|
|
|
for (i=1; i<=NumberOfFlyFrames; i++)
|
|
{
|
|
for (j=0; j<3; j++)
|
|
{
|
|
focalPt[j] = flyFrom[j] + d[j]*i*delta;
|
|
position[j] = positionFrom[j] + d[j]*i*delta;
|
|
}
|
|
ren->GetActiveCamera()->SetFocalPoint(focalPt);
|
|
ren->GetActiveCamera()->SetPosition(position);
|
|
ren->GetActiveCamera()->Dolly(this->Dolly/this->NumberOfFlyFrames + 1.0);
|
|
ren->ResetCameraClippingRange();
|
|
this->Render();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkRenderer* vtkRenderWindowInteractor::FindPokedRenderer(int x,int y)
|
|
{
|
|
vtkRendererCollection *rc;
|
|
vtkRenderer *aren;
|
|
vtkRenderer *currentRenderer=NULL, *interactiveren=NULL, *viewportren=NULL;
|
|
int numRens, i;
|
|
|
|
rc = this->RenderWindow->GetRenderers();
|
|
numRens = rc->GetNumberOfItems();
|
|
|
|
for (i = numRens -1; (i >= 0) && !currentRenderer; i--)
|
|
{
|
|
aren = (vtkRenderer *)rc->GetItemAsObject(i);
|
|
if (aren->IsInViewport(x,y) && aren->GetInteractive())
|
|
{
|
|
currentRenderer = aren;
|
|
}
|
|
|
|
if (interactiveren == NULL && aren->GetInteractive())
|
|
{
|
|
// Save this renderer in case we can't find one in the viewport that
|
|
// is interactive.
|
|
interactiveren = aren;
|
|
}
|
|
if (viewportren == NULL && aren->IsInViewport(x, y))
|
|
{
|
|
// Save this renderer in case we can't find one in the viewport that
|
|
// is interactive.
|
|
viewportren = aren;
|
|
}
|
|
}//for all renderers
|
|
|
|
// We must have a value. If we found an interactive renderer before, that's
|
|
// better than a non-interactive renderer.
|
|
if ( currentRenderer == NULL )
|
|
{
|
|
currentRenderer = interactiveren;
|
|
}
|
|
|
|
// We must have a value. If we found a renderer that is in the viewport,
|
|
// that is better than any old viewport (but not as good as an interactive
|
|
// one).
|
|
if ( currentRenderer == NULL )
|
|
{
|
|
currentRenderer = viewportren;
|
|
}
|
|
|
|
// We must have a value - take anything.
|
|
if ( currentRenderer == NULL)
|
|
{
|
|
aren = rc->GetFirstRenderer();
|
|
currentRenderer = aren;
|
|
}
|
|
|
|
return currentRenderer;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "InteractorStyle: " << this->InteractorStyle << "\n";
|
|
os << indent << "RenderWindow: " << this->RenderWindow << "\n";
|
|
if ( this->Picker )
|
|
{
|
|
os << indent << "Picker: " << this->Picker << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Picker: (none)\n";
|
|
}
|
|
os << indent << "LightFollowCamera: " << (this->LightFollowCamera ? "On\n" : "Off\n");
|
|
os << indent << "DesiredUpdateRate: " << this->DesiredUpdateRate << "\n";
|
|
os << indent << "StillUpdateRate: " << this->StillUpdateRate << "\n";
|
|
os << indent << "Initialized: " << this->Initialized << "\n";
|
|
os << indent << "Enabled: " << this->Enabled << "\n";
|
|
os << indent << "EventPosition: " << "( " << this->EventPosition[0] <<
|
|
", " << this->EventPosition[1] << " )\n";
|
|
os << indent << "LastEventPosition: " << "( " << this->LastEventPosition[0]
|
|
<< ", " << this->LastEventPosition[1] << " )\n";
|
|
os << indent << "EventSize: " << "( " << this->EventSize[0] <<
|
|
", " << this->EventSize[1] << " )\n";
|
|
os << indent << "Viewport Size: " << "( " << this->Size[0] <<
|
|
", " << this->Size[1] << " )\n";
|
|
os << indent << "Number of Fly Frames: " << this->NumberOfFlyFrames <<"\n";
|
|
os << indent << "Dolly: " << this->Dolly <<"\n";
|
|
os << indent << "ControlKey: " << this->ControlKey << "\n";
|
|
os << indent << "ShiftKey: " << this->ShiftKey << "\n";
|
|
os << indent << "KeyCode: " << this->KeyCode << "\n";
|
|
os << indent << "KeySym: " << (this->KeySym ? this->KeySym : "(null)")
|
|
<< "\n";
|
|
os << indent << "RepeatCount: " << this->RepeatCount << "\n";
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::Initialize()
|
|
{
|
|
this->Initialized=1;
|
|
this->Enable();
|
|
this->Render();
|
|
}
|
|
|
|
void vtkRenderWindowInteractor::HideCursor()
|
|
{ this->RenderWindow->HideCursor(); };
|
|
void vtkRenderWindowInteractor::ShowCursor()
|
|
{ this->RenderWindow->ShowCursor(); };
|
|
|
|
|