[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