[vtkusers] Clipping problem when panning
John Platt
jcplatt at dsl.pipex.com
Wed Aug 21 08:52:16 EDT 2013
SnippetHi Serge,
This is the same as ResetCamera() followed by a zoom factor based on the
extreme (x,y) view coordinates rather than a bounding sphere...
void CameraHelper::Fit()
{
// Move the camera so that it's focal point is the centre of the bounding
box
// preserving the view plane normal (vector defined from camera position to
// focal point). The parallel scale is adjusted to maximize the scene in the
// viewport. This is identical to ResetCamera() except the scale factor is
// calculated from extreme x & y rather than the bounding sphere.
// Compute the bounding box of all the visible 3D props in World
coordinates.
double allBounds[6];
m_vtkRenderer->ComputeVisiblePropBounds( allBounds );
// Only proceed if there are visible 3D props.
if ( vtkMath::AreBoundsInitialized( allBounds ) )
{
// Reposition the camera to view the centre point of the visible 3D actors.
// The camera is moved so that it's focal point is the centre of the
bounding
// box, and the distance and position adjusted to preserve the view plane
// normal (vector defined from camera position to focal point).
m_vtkRenderer->ResetCamera();
// Find the extreme x & y positions of the bounding box in View (camera)
// coordinates. The origin of the View coordinate system is the middle of
// the viewport with axes extending from -1 to 1 in all three dimensions.
double maxAbsViewX = -1.0;
double maxAbsViewY = -1.0;
for ( int k = 0; k < 2; k++ )
{
for ( int j = 0; j < 2; j++ )
{
for ( int i = 0; i < 2; i++ )
{
// The View coordinates overwrite the World coordinates and
// therfore the copying cannot be done in the outer loops.
double x = allBounds[i];
double y = allBounds[2+j];
double z = allBounds[4+k];
m_vtkRenderer->WorldToView( x, y, z );
if ( abs( x ) > maxAbsViewX ) maxAbsViewX = abs( x );
if ( abs( y ) > maxAbsViewY ) maxAbsViewY = abs( y );
}
}
}
// Allow a margin so the fit is not too tight.
double viewMargin = PixelsToView( m_marginPixels );
maxAbsViewX += viewMargin;
maxAbsViewY += viewMargin;
// ResetCamera() uses the bounding sphere to fit the props. Calculate a
// new scale ( greater than 1 ) to fit the extreme X or Y. This should be
// close to 1 because of the ResetCamera() call above.
const double* aspectRatio = m_vtkRenderer->GetAspect();
double scaleX = aspectRatio[1]/( maxAbsViewX );
double scaleY = 1.0/maxAbsViewY;
double scale = scaleX > scaleY ? scaleY : scaleX;
// In parallel mode, Zoom() decreases the parallel scale by the specified
// factor. A scale > 1 is a zoom-in, and a scale < 1 is a zoom-out.
m_vtkRenderer->GetActiveCamera()->Zoom( scale );
}
}
Sorry about the format - I use a poor man's mail client.
John.
----- Original Message -----
From: Serge Lalonde
To: vtkusers at vtk.org
Sent: Wednesday, August 21, 2013 1:29 PM
Subject: Re: [vtkusers] Clipping problem when panning
Hi John,
Is that the same as ResetCamera? If not, how is it different and where can I
find the code for it in ParaView? Maybe I can add that also.
Thanks.
On 8/20/2013 5:27 PM, John Platt wrote:
Hi Serge,
If it helps your sanity, I can repeat this clipping problem in VTK 5.10
using the default interactor with QVTKWidget, which I believe is trackball
camera, and parallel projection on.
When this happens, I have a 'Fit' option which moves the focal point of the
camera to the centre of the actors and adjusts the parallel scale to fill
the view.
John.
----- Original Message -----
From: Serge Lalonde
To: vtkusers at vtk.org
Sent: Tuesday, August 20, 2013 8:12 PM
Subject: Re: [vtkusers] Clipping problem when panning
Well, since I got no responses, I dug deeper and found the code in ParaView
that does the rotation and spinning around the center of the visible actors,
extracted it and put it into a vtkInteractorStyleTrackballCamera subclass.
It hasn't been extensively tested yet, but it seems to work well.
Here it is in case it helps save anybody else 3 days of work.
// Our subclass of the trackball camera to change the center of rotation
to be the average
// center of all visible actors instead of the center of the viewport,
which always gets clipped.
// The default implementation is badly broken and doesn't look to be
fixed anytime soon.
// The clipping might be fixed with the changes I submitted:
http://www.vtk.org/Bug/view.php?id=7823
// The new rotation code was taken from ParaView. Specifically,
// - Rotate(): vtkPVTrackballRotate.cxx OnMouseMove()
// - Spin(): vtkPVTrackballRoll.cxx OnMouseMove()
// - UpdateScreenCenterOfRotation(): vtkCameraManipulator.cxx
ComputeDisplayCenter()
class InteractorStyleTrackballCamera: public
vtkInteractorStyleTrackballCamera
{
public:
static InteractorStyleTrackballCamera *New();
vtkTypeMacro(InteractorStyleTrackballCamera,
vtkInteractorStyleTrackballCamera);
// This only gets called is CurrentRenderer isn't NULL.
virtual void StartRotate()
{
Superclass::StartRotate();
UpdateCenterOfRotation(CurrentRenderer);
}
// This only gets called is CurrentRenderer isn't NULL.
virtual void StartSpin()
{
Superclass::StartSpin();
UpdateCenterOfRotation(CurrentRenderer);
UpdateScreenCenterOfRotation(CurrentRenderer);
}
virtual void Rotate()
{
if (CurrentRenderer == NULL)
return;
vtkRenderer *ren= CurrentRenderer;
vtkCamera *camera= ren->GetActiveCamera();
vtkRenderWindowInteractor *rwi= Interactor;
vtkTransform *transform= vtkTransform::New();
double scale= vtkMath::Norm(camera->GetPosition());
if (scale <= 0.0)
{
scale= vtkMath::Norm(camera->GetFocalPoint());
if (scale <= 0.0)
scale= 1.0;
}
double *temp= camera->GetFocalPoint();
camera->SetFocalPoint(temp[0]/scale, temp[1]/scale, temp[2]/scale);
temp= camera->GetPosition();
camera->SetPosition(temp[0]/scale, temp[1]/scale, temp[2]/scale);
double v2[3];
// translate to center
transform->Identity();
transform->Translate(m_center[0]/scale, m_center[1]/scale,
m_center[2]/scale);
int dx= rwi->GetLastEventPosition()[0] -
rwi->GetEventPosition()[0];
int dy= rwi->GetLastEventPosition()[1] -
rwi->GetEventPosition()[1];
// azimuth
camera->OrthogonalizeViewUp();
double *viewUp= camera->GetViewUp();
int *size= ren->GetSize();
transform->RotateWXYZ(360.0*dx/size[0], viewUp[0], viewUp[1],
viewUp[2]);
// elevation
vtkMath::Cross(camera->GetDirectionOfProjection(), viewUp, v2);
transform->RotateWXYZ(-360.0*dy/size[1], v2[0], v2[1], v2[2]);
// translate back
transform->Translate(-m_center[0]/scale, -m_center[1]/scale, -m_center[2]/scale);
camera->ApplyTransform(transform);
camera->OrthogonalizeViewUp();
// For rescale back.
temp= camera->GetFocalPoint();
camera->SetFocalPoint(temp[0]*scale, temp[1]*scale, temp[2]*scale);
temp= camera->GetPosition();
camera->SetPosition(temp[0]*scale, temp[1]*scale, temp[2]*scale);
ren->ResetCameraClippingRange();
rwi->Render();
transform->Delete();
}
virtual void Spin()
{
if (CurrentRenderer == NULL)
return;
vtkRenderer *ren= CurrentRenderer;
vtkCamera *camera= ren->GetActiveCamera();
vtkRenderWindowInteractor *rwi= Interactor;
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];
int x1, x2, y1, y2;
x1= rwi->GetLastEventPosition()[0] - (int) m_display_center[0];
x2= rwi->GetEventPosition()[0] - (int) m_display_center[0];
y1= rwi->GetLastEventPosition()[1] - (int) m_display_center[1];
y2= rwi->GetEventPosition()[1] - (int) m_display_center[1];
if ((x2 == 0.0 && y2 == 0.0) || (x1 == 0.0 && y1 == 0.0))
{
//don't ever want to divide by zero
return;
}
// - divide by magnitudes to get angle
double angle= vtkMath::DegreesFromRadians((x1*y2 -
y1*x2)/(sqrt(static_cast<double>(x1*x1 +
y1*y1))*sqrt(static_cast<double>(x2*x2 + y2*y2))));
// translate to center
vtkTransform *transform= vtkTransform::New();
transform->Identity();
transform->Translate(m_center[0], m_center[1], m_center[2]);
// roll
transform->RotateWXYZ(angle, axis[0], axis[1], axis[2]);
// translate back
transform->Translate(-m_center[0], -m_center[1], -m_center[2]);
camera->ApplyTransform(transform);
camera->OrthogonalizeViewUp();
ren->ResetCameraClippingRange();
rwi->Render();
transform->Delete();
}
protected:
InteractorStyleTrackballCamera()
{
m_center[0]= m_center[1]= m_center[2]= m_display_center[0]=
m_display_center[1]= 0;
}
// Calculate the center of the visible actors.
void UpdateCenterOfRotation(vtkRenderer *ren)
{
vtkActorCollection *actors= ren->GetActors();
vtkCollectionSimpleIterator cookie;
vtkActor *actor;
m_center[0]= m_center[1]= m_center[2]= 0;
actors->InitTraversal(cookie);
while ((actor= actors->GetNextActor(cookie)) != NULL)
{
if (actor->GetVisibility())
{
double *actor_center= actor->GetCenter();
m_center[0]+= actor_center[0];
m_center[1]+= actor_center[1];
m_center[2]+= actor_center[2];
}
}
m_center[0]/= actors->GetNumberOfItems();
m_center[1]/= actors->GetNumberOfItems();
m_center[2]/= actors->GetNumberOfItems();
}
// Updates the screen center of rotation. Must be called after
UpdateCenterOfRotation(),
void UpdateScreenCenterOfRotation(vtkRenderer *ren)
{
double *pt;
// save the center of rotation in screen coordinates
ren->SetWorldPoint(m_center[0], m_center[1], m_center[2], 1.0);
ren->WorldToDisplay();
pt= ren->GetDisplayPoint();
m_display_center[0]= pt[0];
m_display_center[1]= pt[1];
}
private:
double m_center[3], // In model coordinates.
m_display_center[2]; // In display coordinates.
};
vtkStandardNewMacro(InteractorStyleTrackballCamera);
On 8/13/2013 8:59 AM, Serge Lalonde wrote:
I've gotten no replies to this question. Does that mean that no one else has
had this problem?
Can someone please confirm that they're using panning with
vtkInteractorStyleTrackballCamera without any problems in 5.10?
Thanks.
On 8/6/2013 10:49 AM, Serge Lalonde wrote:
I tried panning in ParaView and the clipping works properly. Is it using the
vtkInteractorStyleTrackballCamera or something else?
The problem is that it looks like the rotation center is wrong after
panning, causing the model to be rotated out of the clipping range. It looks
like the rotation center is the center of the window instead of the center
of the model. Also, I have multiple actors in the scene. Could that be a
problem?
I'm not doing anything (that I can tell) to affect this. Could it be a bug
in VTK 5.10? If so, does anyone know of a workaround?
Thanks!
On 8/2/2013 3:59 PM, Serge Lalonde wrote:
I notice that when using the vtkInteractorStyleTrackballCamera panning, I'll
subsequently see a clipping problem if I rotate the actors afterwards.
Calling ResetCameraClippingRange() on the renderer has no effect. I'm using
VTK 5.10.
Is there a workaround for this? It seems like a pretty serious problem. I
searched the archives without much success for a fix for this.
Note: Back in October 2008 (5 years already!), when I was prototyping with
VTK, I posted a fix to vtkusers and www.vtk.org/bug for vtkRenderer and
vtkCamera that fixed a similar clipping problem in VTK 5.2. After examining
the 5.10 source code, it looks like the fix was never integrated into VTK's
official code branch. The page is http://www.vtk.org/Bug/view.php?id=7823
and I noticed that its status is expired. Other users commented in that bug
report that it fixed their problems and some even improved the fix.
--
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at:
http://www.vtk.org/Wiki/VTK_FAQ
Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers
--
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at:
http://www.vtk.org/Wiki/VTK_FAQ
Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers
--
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at:
http://www.vtk.org/Wiki/VTK_FAQ
Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at:
http://www.vtk.org/Wiki/VTK_FAQ
Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers
--
www.infolytica.com
300 Leo Pariseau, Suite 2222, Montreal, QC, Canada, H2X 4B3
(514) 849-8752 x236, Fax: (514) 849-4239
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at:
http://www.vtk.org/Wiki/VTK_FAQ
Follow this link to subscribe/unsubscribe:
http://www.vtk.org/mailman/listinfo/vtkusers
More information about the vtkusers
mailing list