[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