[vtkusers] Shearing a vtkCamera (for head tracking)

Arnold Meijster a.meijster at rc.rug.nl
Fri Mar 4 03:01:24 EST 2005


Hi all,

I've tried to post this mesage yesterday, but
I got back some delivery error mesage from the
mailing list. Therefore I send it again. Sorry,
if you received this twice.

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


-------- Here's my code -----

#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;
}





More information about the vtkusers mailing list