[vtkusers] Re: An unanswered zbuffer question in VTK..................Please Help !!!!!!!!
Deepak Roy
cdeepakroy at gmail.com
Wed Jan 18 12:35:57 EST 2006
Hello Will,
A million thanks for your reply. I greatly appreciate it.
Let us keep the discussion on the mailing list, so other members can benefit
from it. Because this is a problem, that could quite possibly be faced by
anyone who is working on the zbuffer.
*>>>> Regarding the use of vtkWorldPointPicker*
I tried the vtkWorldPointPicker and it was very slow ( render window size
500 x 500 ).
But what i interpret from the information given in the vtk textbook ( "The
VisualizationToolkit - 2nd edition" An Object oriented approach to 3D
graphics - Page Number = 343 ) is that vtkWorldPointPicker just finds the
z-buffer value of the given ( x , y ) position in the render window.
Which i think is in no way different from the information obtained from
vtkRenderWindow::GetZBufferData.
Please correct me if i am wrong ?
If all i get from the vtkWorldPointPicker is the z-buffer value, dont you
think calling vtkWorldPointPicker at each ( x , y ) position in my
offscreen render window would be slower than fetching the z-buffer values
all at once by calling vtkRenderWindow::GetZBufferData.
Please correct me if i am wrong ?
*>>>> Regarding the use of vtkCoordinate*
**
The farthest place i can get using the vtkCoordinate, is to the world
coordinates.
Which is the same as, what your vtkWorldPointPicker returns which is also
similar to the zbuffer information obtained by
vtkRenderWindow::GetZBufferData. Also when i tried using vtkCoordinate
earlier it was very slow.
Now the difference between the two zbuffers i am computing ( to find the
volume ) is relative to the current graphics world i created ( the clipping
plane positions, dimensions of the viewport ). Rememeber i am using
Orthographic i.e. Parallel projection.
My goal is to transform this volume estimate ( which is now relative to the
graphics world i created ) to be independent of the graphics world. So even
if i change the size of the render window, the volume estimate should still
be the same.
If you have not looked at the transformation, i am currently using, here is
the pseudocode :
***************************************************************************************************************
// converts the given zBuffer value to the world coordinates
#define REAL_DEPTH_ORTHO( zBufferVal , zNear , zFar ) ( zNear + zBufferVal *
(zFar - zNear) )
// computes difference between the two zbuffers
for( int x = 0 ; x < wx ; x++ )
{
for( int y = 0 ; y < wy ; y++ )
{
float coons_depth, sphere_depth;
long index = y * wx + x;
sphere_depth = pSphereZBuffer[index];
coons_depth = pCoonsZBuffer[index];
if( !( CHECK_DEPTH( coons_depth ) && CHECK_DEPTH( sphere_depth ) ) ||
CHECK_DEPTH_SIMILARITY( coons_depth , sphere_depth ) )
continue;
coons_depth = REAL_DEPTH_ORTHO( coons_depth , zNear , zFar );
sphere_depth = REAL_DEPTH_ORTHO( sphere_depth , zNear , zFar );
float diff = ( coons_depth - sphere_depth );
if( diff > 0 )
dblSphereVolume += diff;
}
}
// transform the computed volume estimate to be independent of the graphics
world
float scale = pOffScreenRenderer->GetActiveCamera()->GetParallelScale();
float aspect = wx / wy;
float world_x = 2 * scale * aspect;
float world_y = 2 * scale;
dblSphereVolume *= (world_x/wx) * (world_y/wy);
float actual_sphere_volume = ( 2 * vtkMath::Pi() / 3 ) * pow( radius , 3 );
float relative_error = ( actual_sphere_volume - dblSphereVolume ) * 100.0 /
actual_sphere_volume;
************************************************************************************************************************************************
Is this conversion code right ?
Very, Very, Very eagerly waiting for your reply ?
Regards,
Deepak Roy
*Will Schroeder <will.schroeder at kitware.com>* wrote:
I recommend looking at the vtkWorldPointPicker and other pickers for how to
do this. Also look at vtkCoordinate and vtkRenderer for coordinae
transformations.
Will
At 12:12 PM 1/12/2006, Deepak Roy wrote:
Hello,
My name is Deepak Roy. I am a graduate student in the department of computer
science at university of houston and a research assistant in the
Computational Biomedicine Lab ( www.cbl.uh.edu ) at university of houston.
I have sent numerous emails to the mailing list regarding a question in VTK,
but recieved no reply. I have also sent an email before to you and recieved
no reply either.
It would be kind of you if you could look into the question. Below is a
brief description of it.
It would also be helpful, if you could give me a contact number of the VTK
Tech support people.
Very Eagerly waiting for a reply, from the VTK Tech Support.
Regards,
&nbs!
p;
Deepak Roy
Email:
cdeepakroy at yahoo.com<http://us.f303.mail.yahoo.com/ym/Compose?To=cdeepakroy@yahoo.com>
drchitta at mail.uh.edu<http://us.f303.mail.yahoo.com/ym/Compose?To=drchitta@mail.uh.edu>
*************************************************************************************************
*Subject:*
How to convert the z-buffer depth values to z-values in the world coordinate
system ?
*Problem I am trying to solve:
*
I am trying to get the volume enclosed between a hemisphere like surface and
a plane like surface which lies at the base of the hemispherical surface.
These surfaces are extracted from the mesh of a human body.
I want to use the z-buffer difference to estimate the enclosed volume, since
it is more quick compared to vtkMassProperties. At the end i will compare
with vtkMassProperties estimate. I very well know this can be done with
other alternatives, but i want to use the z-buffer difference only first to
see how it works.
*Approach i am following:
*
To simplify my problem, here are the steps i am following
1. I first created a simple hemisphere actor using vtkSphereSource
2. Next i create a simple square Plane actor which represents the base
of the hemispherical surface.
3. Now i create an off screen render window using
*vtkWin32OpenGLRenderWindow.
*
4. I make the renderer to use OrthographicProjection using
vtkRenderer::ParallelProjectionOn.
5. Then i first render both actors to the renderer.
6. I get the z-buffer data of the render window using
vtkRenderWindow::GetZBufferData with the hemisphere and cache it.
7. Then i hide the hemipherical actor using vtkActor::VisibilityOff.
8. Then i get the z-buffer data of the plane actor.
9. Now i compute the cumulative difference between the two zbuffers
which is an estimate of the volume.
*Difficulty:
*
I rendered the off screen render window for both actors to a disk image
using vtkWindowToImageFilter and both the images come perfectly as expected.
The images are attached to the message if you want to take a look.
*Now the difficulty is this estimate of the volume is relative to the
graphic world i created.
*
*How do i convert it to an est! imate of the real volume ? which factor or
scales should i multiply the z-buffer differnce with to get the volume ?
*
How do i back transform the ZBuffer values? I came to know there is
something called gluUnProject in opengl GLUT. Is there anything similar in
VTK.
Can i use opengl commands amidst VTK code ?
*Email Attachments:
*
- the C++ test code i am using - zbuffer_test.cxx. You can run and test the
C++ file if you want.
- the z-buffer image i obtained for the hemisphere - sphere-zbuffer.jpg
- the z-buffer image i obtained for the underlying plane -
coons_zbuffer.jpg
Can Anyone tell me whats going wrong ? It would be a great help ....
What do! those z-values mean ??
Thanks in Advance.
Regards,
Deepak
Yahoo! Photos
Ring in the New Year with Photo
Calendars<http://us.rd.yahoo.com/mail_us/taglines/photos/*http://pa.yahoo.com/*http://us.rd.yahoo.com/mail_us/taglines/photos/evt=38087/*http://pg.photos.yahoo.com/ph//page?.file=calendar_splash.html&.dir=>.
Add photos, events, holidays, whatever.
// VTK INCLUDES
#include "vtkOpenGLRenderer.h"
#include "vtkWin32OpenGLRenderWindow.h"
#include "vtkRenderWindowInteractor.h "
#include "vtkOpenGLActor.h"
#include "vtkCamera.h"
#include "vtkProperty.h"
#include "vtkMatrix4x4.h"
#include "vtkSphereSource.h"
#include " vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkCellArray.h"
#include "vtkImageData.h"
#include "vtkPointData.h"
#include "vtkCoordinate.h"
#include "vtkMath.h"
#include "vtkWindowToImageFilter.h"
#include "vtkJPEGWriter.h"
// STD INCLUDES
#include "conio.h"
// CUSTOM MACROS
#define CHECK_DEPTH( depth ) ( depth > 0.0 && depth < 1.0 )
#define CHECK_DEPTH_SIMILARITY( d1 , d2 ) ( d1 == d2 )
#define REAL_DEPTH( zBufferVal , zNear , zFar ) ( zNear * zFar / (
zBufferVal * (zNear - zFar ) + zFar ) )
void WriteZBufferToImage( int wx , int wy , float *pBuffer , const char
*strImageFile )
{
vtkImageData *pZImage = vtkImageData::New();
pZImage->SetExtent( 0 , wx , 0 , wy , 0 , 0 );
pZImage->SetOrigin( 0.0 , 0.0 , 0.0 );
pZImage->SetSpacing( 1.0 , 1.0 , 1.0 );
pZImage->SetScalarTypeToUnsignedChar();
pZImage->SetNumberOfScalarComponents( 1 );
pZImage->AllocateScalars();
unsigned char *zPtr = (unsigned char *) pZImage->GetScalarPointer( 0
, 0 , 0 );
for( int i = 0 ; i < (wx * wy) ; i++ )
{
zPtr[i] = pBuffer[i] * 255;
}
vtkJPEGWriter *pSphereImageWriter = vtkJPEGWriter::New();
pSphereImageWriter->SetInput( pZImage );
pSphereImageWriter->SetQuality( 40.0 );
pSphereImageWriter->SetFileName( strImageFile );
pSphereImageWriter->ProgressiveOff();
pSphereImageWriter->Write();
}
void WriteWindowToImage( vtkWindow *pWindow , const char *strImageFile )
{
// write window to disk image
vtkWindowToImageFilter *pWindowImageFilter =
vtkWindowToImageFilter::New();
pWindowImageFilter->SetInput( pWindow );
vtkImageData *pImage = pWindowImageFilter->GetOutput();
vtkJPEGWriter *pSphereImageWriter = vtkJPEGWriter::New();
pSphereImageWriter->SetInput( pImage );
pSphereImageWriter->SetQuality( 100.0 );
pSphereImageWriter->SetFileName( strImageFile );
pSphereImageWriter->ProgressiveOff();
pSphereImageWriter->Write();
pSphereImageWriter->Delete();
pWindowImageFilter->Delete();
}
vtkActor *BuildSphereActor( float radius )
{
vtkSphereSource *pSphere = vtkSphereSource::New();
pSphere->SetCenter( 0.0 , 0.0 , 0.0 );
pSphere->SetRadius( radius );
pSphere->SetStartTheta( 0.0 );
pSphere->SetEndTheta( 360.0 );
pSphere->SetThetaResolution( 30.0 );
pSphere->SetStartPhi( 0.0 );
pSphere->SetEndPhi( 90.0 );
pSphere->SetPhiResolution( 30.0 );
vtkPolyDataMapper *pSphereMapper = vtkPolyDataMapper::New();
pSphereMapper->SetInput( pSphere->GetOutput() );
pSphereMapper->Update();
vtkOpenGLActor *pSphereActor = vtkOpenGLActor::New();
pSphereActor->SetMapper( pSphereMapper );
pSphereActor->GetProperty()->SetColor( 1.0 , 0.0 , 0.0 );
return pSphereActor;
}
vtkActor *BuildPlaneActor( float sphereBounds[6] )
{
vtkPolyData *pCoonsPlane = vtkPolyData::New();
vtkPoints *pMeshPoints;
vtkCellArray *pMeshCells;
// allocate space for points
pMeshPoints = vtkPoints::New();
pMeshPoints->Allocate( 4 );
pMeshPoints->InsertNextPoint( sphereBounds[0] ,
sphereBounds[2] , 0.0 );
pMeshPoints->InsertNextPoint( sphereBounds[0] ,
sphereBounds[3] , 0.0 );
pMeshPoints->InsertNextPoint( sphereBounds[1] ,
sphereBounds[3] , 0.0 );
pMeshPoints->InsertNextPoint( sphereBounds[1] ,
sphereBounds[2] , 0.0 );
// allocate space for cells
pMeshCells = vtkCellArray::New();
pMeshCells->Allocate( pMeshCells->EstimateSize( 1 , 4 ) );
vtkIdType pts[4];
pts[0] = 0;
pts[1] = 1;
pts[2] = 2;
pts[3] = 3;
pMeshCells->InsertNextCell( 4 , pts );
pCoonsPlane->SetPoints( pMeshPoints );
pCoonsPlane->SetPolys( pMeshCells );
pMeshPoints->Delete();
pMeshCells->Delete();
vtkPolyDataMapper *pCoonsMapper = vtkPolyDataMapper::New();
pCoonsMapper->SetInput( pCoonsPlane );
pCoonsMapper->Update();
vtkOpenGLActor *pCoonsActor = vtkOpenGLActor::New();
pCoonsActor->SetMapper( pCoonsMapper );
return pCoonsActor;
}
void main()
{
// create Sphere actor first
float radius = 10.0;
vtkActor *pSphereActor = BuildSphereActor( radius );
float sphereBounds[6];
pSphereActor->GetBounds( sphereBounds );
// build coons actor
vtkActor *pCoonsActor = BuildPlaneActor( sphereBounds );
// setup rendering
vtkOpenGLRenderer *pOffScreenRenderer = vtkOpenGLRenderer::New();
// add actors
pOffScreenRenderer->AddActor( pSphereActor );
pOffScreenRenderer->AddActor( pCoonsActor );
// set parallel projection
pOffScreenRenderer->GetActiveCamera()->ParallelProjectionOn();
double wx, wy;
wx = 500;
wy = 500;
vtkWin32OpenGLRenderWindow *pOffScreenRenderWindow =
vtkWin32OpenGLRenderWindow::New();
pOffScreenRenderWindow->OffScreenRenderingOn();
pOffScreenRenderWindow->AddRenderer( pOffScreenRenderer );
pOffScreenRenderWindow->SetSize( wx , wy );
pOffScreenRenderWindow->Start();
// show only breast actor
pOffScreenRenderer->Render();
// write window to disk image
WriteWindowToImage( pOffScreenRenderWindow , "sphere_window.jpg" );
// get Sphere zbuffer
float *pSphereZBuffer = pOffScreenRenderWindow->GetZbufferData( 0 ,
0 , wx , wy );
WriteZBufferToImage( wx , wy , pSphereZBuffer , "sphere_zbuffer.jpg" );
// show only coons actor
pSphereActor->VisibilityOff();
pOffScreenRenderer->Render();
// write window to disk image
WriteWindowToImage( pOffScreenRenderWindow , "coons_window.jpg" );
// get Sphere zbuffer
float *pCoonsZBuffer = pOffScreenRenderWindow->GetZbufferData( 0 , 0
, wx , wy );
// write z buffer to disk
WriteZBufferToImage( wx , wy , pCoonsZBuffer , "coons_zbuffer.jpg"
);
// compute diffrence
double dblSphereVolume = 0.0;
float clip_range[2];
pOffScreenRenderer->GetActiveCamera()->GetClippingRange( clip_range
);
float zNear = clip_range[0];
float zFar = clip_range[1];
printf( "\n zNear = %f , zFar = %f" , zNear , zFar );
for( int x = 0 ; x < wx ; x++ )
{
for( int y = 0 ; y < wy ; y++ )
{
float coons_depth, sphere_depth;
long index = y * wx + x;
sphere_depth = pSphereZBuffer[index];
coons_depth = pCoonsZBuffer[index];
if( !( CHECK_DEPTH( coons_depth ) && CHECK_DEPTH(
sphere_depth ) ) || CHECK_DEPTH_SIMILARITY( coons_depth , sphere_depth ) )
continue;
float diff = ( coons_depth - sphere_depth );
if( diff > 0 )
dblSphereVolume += diff;
}
}
float sphere_volume = ( 2 * vtkMath::Pi() / 3 ) * pow( radius , 3 );
printf( "\ncomputed Sphere volume = %f, actual sphere volume = %f\n"
, dblSphereVolume , sphere_volume );
getch();
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20060118/244f9a02/attachment.htm>
More information about the vtkusers
mailing list