[vtkusers] Synthetic range image generation

Miller, James V (CRD) millerjv at crd.ge.com
Wed Feb 14 10:48:04 EST 2001


It is pretty much that simple.  The best approach is grab the entire z-buffer in one call and run
through the inverse transform for each pixel. Here is some snippets of code which runs z-buffer
values through the inverse perspective transform, then generates world x,y,z coordinates using the
inverse view transform.  Note that this only works on systems that have a z-buffer. Some graphics
cards have a w-buffer and this inverse code will not work properly on those.


  zBuffer = this->Renderer->GetRenderWindow()
    ->GetZbufferData(0, 0, dims[0]-1, dims[1]-1);
  zPtr = zBuffer;
  
  rangeBuffer = new float[ dims[0] * dims[1] ];
  rangeBuffer2 = new float[ dims[0] * dims[1] ];


  // Some are copied from Lisa's vtkOpenGLProjectedPolydataRayBounder.cxx
  rayCaster = this->Renderer->GetRayCaster();

  // Create some objects that we will need later
  transformDisp       = vtkTransform::New();
  matrixDisp          = vtkMatrix4x4::New();  
  transformView       = vtkTransform::New();
  matrixView          = vtkMatrix4x4::New();  

  // Get the aspect ratio of the RenderWindow
  this->Renderer->GetAspect( renAspect );
  aspect = renAspect[0]/renAspect[1];
    
  // Create the perspective matrix for the camera.  This will be used
  // to decode z values, so we will need to invert it
  transformDisp->SetMatrix(this->Renderer->GetActiveCamera()
			    ->GetPerspectiveTransformMatrix(aspect,-1,1));
  transformDisp->Inverse();
    
  // To speed things up, we pull the matrix out of the transform. 
  // This way, we can decode z values faster since we know which elements
  // of the matrix are important, and which are zero.
  transformDisp->GetMatrix( matrixDisp );
    
  // These are the important elements of the matrix.  We will decode
  // z values by taking the znum1 and dividing by the zbuffer z value times
  // zdenom1 plus zdenom2.
  zNumerator   = matrixDisp->Element[2][3];
  zDenomMult   = matrixDisp->Element[3][2];
  zDenomAdd    = matrixDisp->Element[3][3];

  rangePtr = rangeBuffer;
  rayBuffer = rayCaster->GetPerspectiveViewRays();
  rayPtr = rayBuffer;
  rayPtr += 2;

  // Convert  the ZBuffer to range values
  // j is row, i is column
  for ( j = 0; j < dims[1]; j++ )
    {
    for ( i = 0; i < dims[0]; i++ )
      {
      *(rangePtr) = (-zNumerator / ( ((*(zPtr++))*2.0 -1.0) *
           zDenomMult + zDenomAdd )) / (-(*rayPtr));

      rangePtr++;
      rayPtr += 3;
      }
    }


  // Create the view matrix.  This will be used to transform camera
  // coordinates to world coordinates, so we will need to invert it
  transformView
    ->SetMatrix(this->Renderer->GetActiveCamera()->GetViewTransformMatrix());
  transformView->Inverse();
    
  // To speed things up, we pull the matrix out of the transform.
  transformView->GetMatrix( matrixView );

  // Use ray trace value to calculate camera coordinates
  rayPtr = rayBuffer;
  rangePtr = rangeBuffer;

  zPtr   = zBuffer;
  zbuf_tolerance = 1.0e-5;

  int offset;

  point[3] = 1.0;
  vtkDebugMacro( << "Outputting range/scalars" );
  for ( j = 0; j < dims[1]; j++ )
    {
    for ( i = 0; i < dims[0]; i++ )
      {
      point[0] = (*rangePtr) * (*(rayPtr++));
      point[1] = (*rangePtr) * (*(rayPtr++));
      point[2] = (*rangePtr) * (*(rayPtr++));

      matrixView->MultiplyPoint(point, point1);
      
      offset = j*dims[0] + i;
      point1[0] /= point1[3];
      point1[1] /= point1[3];
      point1[2] /= point1[3];
      point1[3] = 1.0;
      points->SetPoint(offset, point1);

      // Set range to -1 if the range falls outside the depth of field
      if (*rangePtr <= this->MinDepthOfField
          || *rangePtr >= this->MaxDepthOfField)
        {
	  *rangePtr = -1;
        }

      // Check for extreme bounds of the Z buffer
      if (*zPtr < zbuf_tolerance || (1 - *zPtr) < zbuf_tolerance)
	{
	*rangePtr = -1;
	}

      scalars->SetScalar(offset, *rangePtr);
      rangePtr++;
      zPtr++;
      }
    }
  output->SetPoints(points);
  output->GetPointData()->SetScalars(scalars);



-----Original Message-----
From: Gerald Dalley [mailto:dalleyg at dma.org]
Sent: Tuesday, February 13, 2001 4:36 PM
To: VTK Users
Subject: [vtkusers] Synthetic range image generation


I am attempting to create some synthetic range images using VTK.  I've
noticed that there is a vtkRenderWindow::GetZ method that will give me the Z
value for a pixel, but I need the scene X and Y coordinates also.
Preferably, I'd like to get the world (X,Y,Z) coordinates for everything.

Is this as simple as multiplying (screenX, screenY, GetZValue) by the
inverse of the ViewTransformMatrix of the current camera, or is there more
involved than this?

--Gerald Dalley
  dalleyg at ee.eng.ohio-state.edu


_______________________________________________
This is the private VTK discussion list. 
Please keep messages on-topic. Check the FAQ at: <http://public.kitware.com/cgi-bin/vtkfaq>
Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/vtkusers




More information about the vtkusers mailing list