Quantcast

Re: An unanswered zbuffer question in VTK..................Please Help !!!!!!!!

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: An unanswered zbuffer question in VTK..................Please Help !!!!!!!!

Deepak Roy Chittajallu
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 <[hidden email]> 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 ( <a onclick="return top.js.OpenExtLink(window,event,this)" href="http://www.cbl.uh.edu/" target="_blank">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:
 
<a onclick="return top.js.OpenExtLink(window,event,this)" href="http://us.f303.mail.yahoo.com/ym/Compose?To=cdeepakroy@yahoo.com" target="_blank"> cdeepakroy@...
<a onclick="return top.js.OpenExtLink(window,event,this)" href="http://us.f303.mail.yahoo.com/ym/Compose?To=drchitta@mail.uh.edu" target="_blank">drchitta@...
 
*************************************************************************************************
 
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 <a onclick="return top.js.OpenExtLink(window,event,this)" href="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&amp;.dir=" target="_blank"> Photo Calendars. 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();
}

 

_______________________________________________
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
Loading...