[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