[vtkusers] Shearing a vtkCamera (for head tracking use)

Michael Scarpa M.Scarpa at uva.nl
Mon Mar 7 04:04:08 EST 2005


Hi Arnold,

I have already used VTK for head tracking.

The vtkCamera::SetViewShear method uses the 
vtkPerspectiveTransform::Shear method. Now, I looked into the source of 
that ($VTK_SRC/Common/vtkPerspectiveTransform.cxx), and found a quite 
extensive comment on how to use the Shear method for head tracking 
right above the definition of that method. That should help you.

There is one tweak though: vtkCamera calls 
vtkPerspectiveTransform::Shear like this:
     this->PerspectiveTransform->Shear(this->ViewShear[0],
                                       this->ViewShear[1],
                                       
this->ViewShear[2]*this->Distance);
ViewShear is an array with the three values set through 
vtkCamera::SetViewShear. In my experience, this translates to a call to 
vtkCamera::SetViewShear with the first parameter set to dx/dz, the 
second set to dy/dz, and the third to 1.0, since that one 
(ViewShear[2]) will then be multiplied by the distance from the eye 
position to the view plane, which is what we want anyway (this might 
make sense only after reading the comments in 
vtkPerspectiveTransform.cxx).

I hope this helps you out. Feel free to contact me if you want to 
discuss this further.

Kind regards,

Michael Scarpa


Section Computational Science
Universiteit van Amsterdam
Kruislaan 403
1098 SJ Amsterdam, The Netherlands
Room F2.15
Tel: +31 20 525 7574
Fax: +31 20 525 7419


On Mar 4, 2005, at 0:24, <a.meijster at rc.rug.nl> wrote:

>
>
> Hi all,
>
> I'm trying to use VTK for stereo rendering on
> a stero projection system using head tracking.
> At each moment of time the tracker can yield me
> the 3D coordinates of the viewer's eyes and
> the orientation (view direction). Now, let's assume
> the screen is 2.5x2.5 meters, and the origin of the
> 3D world is chosen such that the center of the
> projection screen is at (0,0,-1.25), i.e.
> the screen is at distance 1.25 from the origin.
>
> The field of view (viewangle) is 90 degrees.
>
>
> Now, I wrote the follwing small code snippet to
> simulate a user that views a cube of size 50x50x50 cm.,
> which has its front face in the projection screen,
> and for the rest lies behind the screen.
>
> Now, if a user stands in front of the screen, moving
> along the line z=0, and y=0 (only x varies), he/she
> should see that the front face of the cube stays
> at the same place, while the faces behind the screen
> change (of course).
>
> Now, my problem. How do you program this? I believe
> I should use a sheared camera, since the projection
> screen (obviously) stays at the same place when
> a user moves. However, I don't understand the text
> given in the doxygen manual page of vtkCamera at
> all. There are methods setViewShear and
> SetObliqueAngles. I believe I need only
> one of these two (is that right?). However,
> both descriptions are completely incomprehensible to me.
> I wrote a small program that renders with a camera
> at (0,0,0) looking perpendicular to the screen, and sleep
> for a second. Than it moves the camera to (0.5,0,0) (half
> a meter further) and it (should) render a new image.
> What I expect to see is that the front face does not get
> distorted and stays rectangular (and in the projection
> plane). However, it doesn't.
>
> Can anyone please txplain me how to do this, or
> even better, send me the corrected code?
>
> All help is very much appreciated.
>
> Regards,
>
>   Arnold Meijster
>
>
> #include <iostream>
>
> #include "vtkCubeSource.h"
> #include "vtkSphereSource.h"
> #include "vtkPolyDataMapper.h"
> #include "vtkRenderWindow.h"
> #include "vtkCamera.h"
> #include "vtkActor.h"
> #include "vtkRenderer.h"
> #include "vtkProperty.h"
>
> using namespace std;
>
> void AddSphere (double cx, double cy, double cz,
> 		double radius,
> 		double r, double g, double b,
> 		int wireframe, vtkRenderer *ren) {
>   vtkSphereSource *sphere = vtkSphereSource::New();
>   sphere->SetCenter(cx, cy, cz);
>   sphere->SetRadius(radius);
>
>   vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
>   sphereMapper->SetInput( sphere->GetOutput() );
>   vtkActor *sphereActor = vtkActor::New();
>   sphereActor->SetMapper( sphereMapper );
>   sphereActor->GetProperty()->SetColor(r,g,b);
>   if (wireframe) {
>     sphereActor->GetProperty()->SetRepresentationToWireframe();
>   }
>   ren->AddActor(sphereActor );
> }
>
> int main(int argc, char *argv[]) {
>   float headpos[3], wandpos[3];
>   float headorn[3], wandorn[3];
>
>   vtkRenderer *ren1= vtkRenderer::New();
>   ren1->SetBackground( 0.5, 0.5, 0.5 );
>
>   vtkRenderWindow *renWin = vtkRenderWindow::New();
>  renWin->AddRenderer( ren1 );
>
> #if 1
>   renWin->StereoCapableWindowOn();
>   renWin->SetStereoTypeToCrystalEyes();
>   renWin->StereoRenderOn();
> #endif
>
>   renWin->SetSize(500, 500);
>
>   // Add a cube to the scene. Its front
>   // face lies in the screen.
>   vtkCubeSource *cube = vtkCubeSource::New();
>   vtkCamera *camera;
>   cube->SetCenter(0,0,-1.5);
>   cube->SetXLength(0.5);
>   cube->SetYLength(0.5);
>   cube->SetZLength(0.5);
>   vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New();
>   cubeMapper->SetInput( cube->GetOutput() );
>   vtkActor *cubeActor = vtkActor::New();
>   cubeActor->SetMapper( cubeMapper );
>   cubeActor->GetProperty()->SetRepresentationToWireframe();
>   ren1->AddActor( cubeActor );
>
>
>   AddSphere (0, 0, -1.25, 0.05,
> 	     0.0, 1.0, 0.0,   /* green */
> 	     0, ren1);
>
>   // Add a small white sphere on top of cube.
>   // This sphere is used to see if the camera is not upside down :-)
>   AddSphere (0, 0.25, -1.25, 0.01,
> 	     1.0, 1.0, 1.0,   /* white */
> 	     0, ren1);
>
>   // Add spheres in each corner
>   AddSphere (-1.25, -1.25, -1.25, 0.03,      /* left,bottom  */
> 	     1.0, 1.0, 0.0,   /* yellow */
> 	     0, ren1);
>   AddSphere (-1.25, +1.25, -1.25, 0.03,      /* left,top     */
> 	     1.0, 1.0, 0.0,   /* yellow */
> 	     0, ren1);
>   AddSphere (+1.25, -1.25, -1.25, 0.03,      /* right,bottom */
> 	     1.0, 1.0, 0.0,   /* yellow */
> 	     0, ren1);
>   AddSphere (+1.25, +1.25, -1.25, 0.03,      /* right,top    */
> 	     1.0, 1.0, 0.0,   /* yellow */
> 	     0, ren1);
>
>
>   int even=0;
>   double dxdz, dydz, c;
>   camera = ren1->GetActiveCamera();
>   while(1) {
>     camera->SetViewAngle(90);
>     camera->SetClippingRange(0.01, 1000.0);
>     camera->SetViewUp  (0, 1, 0);
>     if (even) {
>       camera->SetPosition(0, 0, 0);
>       camera->SetFocalPoint (0, 0, -1.25);
>       camera->SetViewShear(0,0,1);
>     } else {
>       camera->SetPosition(0.5, 0, 0);
>       camera->SetFocalPoint (0.5, 0, -1.25);
>       // WHAT SHOULD BE THE CORRECT VALUES FOR SHEARING?
>       // We don't have shear in vertical direction,
>       // so I expect dydz=0. I also expect that
>       // dxdz=1.25/0.5=0.4, but I'm not sure about this.
>       // center is completely unclear to me. I tried center
>       // center=1, and center=0 and some random values in between.
>       // Nothing seems right.
>       camera->SetViewShear(0.4,0,0);
>     }
>     even = 1-even;
>     camera->GetViewShear(dxdz, dydz, c);
>     printf ("fd=%f: dxdz=%f, dydz=%f, center=%f\n",
> 	    camera->GetDistance(),
> 	    dxdz, dydz, c);
>     // render the image
>     renWin->Render();
>     // wait a second
>     sleep(1);
>   }
>   return 0;
> }
>
>
> ========================================================
> Dr. Arnold Meijster
> Center for High Performance Computing & Visualization,
> Nettelbosje 1,
> 9747 AJ Groningen, Netherlands
>
> e-mail: a.meijster at rc.rug.nl
> tel:    +31 50 363 9246
> mobile: +31  6 184 89 380
> _______________________________________________
> This is the private VTK discussion list.
> Please keep messages on-topic. Check the 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