<div>Hello Will,</div>
<div> </div>
<div>A million thanks for your reply. I greatly appreciate it.</div>
<div> </div>
<div>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.</div>
<div> </div>
<div><strong>>>>> Regarding the use of vtkWorldPointPicker</strong></div>
<div> </div>
<div>I tried the vtkWorldPointPicker and it was very slow ( render window size 500 x 500 ).</div>
<div> </div>
<div>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.
</div>
<div> </div>
<div>Which i think is in no way different from the information obtained from vtkRenderWindow::GetZBufferData.</div>
<div> </div>
<div>Please correct me if i am wrong ?</div>
<div> </div>
<div>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.
</div>
<div> </div>
<div>Please correct me if i am wrong ?</div>
<div> </div>
<div>
<div><strong>>>>> Regarding the use of vtkCoordinate</strong></div>
<div><strong></strong> </div>
<div>The farthest place i can get using the vtkCoordinate, is to the world coordinates.</div>
<div> </div>
<div>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.
</div>
<div> </div>
<div>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.</div>
<div> </div>
<div>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.
</div>
<div> </div>
<div>If you have not looked at the transformation, i am currently using, here is the pseudocode :</div>
<div><font color="#0000ff" size="2"></font> </div>
<div>***************************************************************************************************************</div>
<div> </div>
<div><font color="#0000ff" size="2">// converts the given zBuffer value to the world coordinates</font></div>
<div><font color="#0000ff" size="2">#define</font><font size="2"> REAL_DEPTH_ORTHO( zBufferVal , zNear , zFar ) ( zNear + zBufferVal * (zFar - zNear) )</font></div>
<div> </div>
<div>// computes difference between the two zbuffers</div>
<div>for( int x = 0 ; x < wx ; x++ )<br>{<br> for( int y = 0 ; y < wy ; y++ ) <br> {<br> float coons_depth, sphere_depth;<br> long index = y * wx + x;</div>
<p> sphere_depth = pSphereZBuffer[index];<br> coons_depth = pCoonsZBuffer[index];</p>
<p> if( !( CHECK_DEPTH( coons_depth ) && CHECK_DEPTH( sphere_depth ) ) || CHECK_DEPTH_SIMILARITY( coons_depth , sphere_depth ) )<br> continue;</p>
<p> coons_depth = REAL_DEPTH_ORTHO( coons_depth , zNear , zFar );<br> sphere_depth = REAL_DEPTH_ORTHO( sphere_depth , zNear , zFar );</p>
<p> float diff = ( coons_depth - sphere_depth );</p>
<p> if( diff > 0 )<br> dblSphereVolume += diff;<br> }<br>}</p>
<p>// transform the computed volume estimate to be independent of the graphics world<br>float scale = pOffScreenRenderer->GetActiveCamera()->GetParallelScale();<br>float aspect = wx / wy;<br>float world_x = 2 * scale * aspect;
<br>float world_y = 2 * scale;</p>
<p>dblSphereVolume *= (world_x/wx) * (world_y/wy);</p>
<p>float actual_sphere_volume = ( 2 * vtkMath::Pi() / 3 ) * pow( radius , 3 );</p>
<p>float relative_error = ( actual_sphere_volume - dblSphereVolume ) * 100.0 / actual_sphere_volume;<br></p>
<p>************************************************************************************************************************************************</p></div>
<div>
<div>Is this conversion code right ?</div>
<div> </div>
<div>Very, Very, Very eagerly waiting for your reply ?</div>
<div> </div>
<div>Regards,</div>
<div> </div>
<div>Deepak Roy</div>
<div> </div>
<div><br><b><i>Will Schroeder <<a onclick="return top.js.OpenExtLink(window,event,this)" href="mailto:will.schroeder@kitware.com" target="_blank">will.schroeder@kitware.com</a>></i></b> wrote:</div></div>
<blockquote style="PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #1010ff 2px solid">I recommend looking at the vtkWorldPointPicker and other pickers for how to do this. Also look at vtkCoordinate and vtkRenderer for coordinae transformations.
<br>Will<br><br>At 12:12 PM 1/12/2006, Deepak Roy wrote:<br>
<blockquote cite="http://" type="cite">Hello,<br> <br>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"><font color="#003399">www.cbl.uh.edu</font></a> ) at university of houston.<br> <br>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.
<br> <br>It would be kind of you if you could look into the question. Below is a brief description of it.<br> <br>It would also be helpful, if you could give me a contact number of the VTK Tech support people.<br> <br>Very Eagerly waiting for a reply, from the VTK Tech Support.
<br> <br>Regards,<br>&nbs!<br>p;<br>Deepak Roy<br> <br>Email:<br> <br><font color="#003399"><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@yahoo.com</a><br><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@mail.uh.edu</a><br></font> <br>*************************************************************************************************
<br> <br><b>Subject:</b> <br> <br>How to convert the z-buffer depth values to z-values in the world coordinate system ? <br> <br><b>Problem I am trying to solve:<br></b> <br>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.
<br> <br>These surfaces are extracted from the mesh of a human body. <br> <br>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.
<br> <br><b>Approach i am following: <br></b> <br>To simplify my problem, here are the steps i am following<br>
<ol>
<li>I first created a simple hemisphere actor using vtkSphereSource
<li>Next i create a simple square Plane actor which represents the base of the hemispherical surface.
<li>Now i create an off screen render window using <b>vtkWin32OpenGLRenderWindow. </b>
<li>I make the renderer to use OrthographicProjection using vtkRenderer::ParallelProjectionOn.
<li>Then i first render both actors to the renderer.
<li>I get the z-buffer data of the render window using vtkRenderWindow::GetZBufferData with the hemisphere and cache it.
<li>Then i hide the hemipherical actor using vtkActor::VisibilityOff.
<li>Then i get the z-buffer data of the plane actor.
<li>Now i compute the cumulative difference between the two zbuffers which is an estimate of the volume. </li></li></li></li></li></li></li></li></li></ol><b>Difficulty:<br></b> <br>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.
<br> <br><b><i>Now the difficulty is this estimate of the volume is relative to the graphic world i created.<br></i></b> <br><b><i>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 ?
<br></i></b> <br>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.<br> <br>Can i use opengl commands amidst VTK code ?<br>
<br><b>Email Attachments:<br></b> <br>
<dl>
<dd>- the C++ test code i am using - zbuffer_test.cxx. You can run and test the C++ file if you want.<br>
<dd><br>
<dd>- the z-buffer image i obtained for the hemisphere - sphere-zbuffer.jpg<br>
<dd><br>
<dd>- the z-buffer image i obtained for the underlying plane - coons_zbuffer.jpg<br><br></dd></dd></dd></dd></dd></dl> <br>Can Anyone tell me whats going wrong ? It would be a great help .... <br> <br>What do! those z-values mean ??
<br> <br>Thanks in Advance.<br> <br>Regards,<br> <br>Deepak<br><br><br>Yahoo! Photos<br>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&.dir=" target="_blank">
Photo Calendars</a>. Add photos, events, holidays, whatever. <br><br><br>// VTK INCLUDES<br>#include "vtkOpenGLRenderer.h"<br>#include "vtkWin32OpenGLRenderWindow.h"<br>#include "vtkRenderWindowInteractor.h
"<br>#include "vtkOpenGLActor.h"<br>#include "vtkCamera.h"<br>#include "vtkProperty.h"<br>#include "vtkMatrix4x4.h"<br><br>#include "vtkSphereSource.h"<br>#include "
vtkPolyData.h"<br>#include "vtkPolyDataMapper.h"<br>#include "vtkCellArray.h"<br>#include "vtkImageData.h"<br>#include "vtkPointData.h"<br>#include "vtkCoordinate.h"<br>
#include "vtkMath.h"<br><br>#include "vtkWindowToImageFilter.h"<br>#include "vtkJPEGWriter.h"<br><br>// STD INCLUDES<br>#include "conio.h"<br><br>// CUSTOM MACROS<br>#define CHECK_DEPTH( depth ) ( depth >
0.0 && depth < 1.0 ) <br>#define CHECK_DEPTH_SIMILARITY( d1 , d2 ) ( d1 == d2 )<br>#define REAL_DEPTH( zBufferVal , zNear , zFar ) ( zNear * zFar / ( zBufferVal * (zNear - zFar ) + zFar ) )<br><br>void WriteZBufferToImage( int wx , int wy , float *pBuffer , const char *strImageFile )
<br>{<br> vtkImageData *pZImage = vtkImageData::New();<br><br> pZImage->SetExtent( 0 , wx , 0 , wy , 0 , 0 );<br> pZImage->SetOrigin( 0.0 , 0.0 , 0.0 );<br> pZImage->SetSpacing( 1.0
, 1.0 , 1.0 );<br> pZImage->SetScalarTypeToUnsignedChar();<br> pZImage->SetNumberOfScalarComponents( 1 );<br> pZImage->AllocateScalars();<br> <br> unsigned char *zPtr = (unsigned char *) pZImage->GetScalarPointer( 0 , 0 , 0 );
<br><br> for( int i = 0 ; i < (wx * wy) ; i++ )<br> {<br> zPtr[i] = pBuffer[i] * 255;<br> }<br><br> vtkJPEGWriter *pSphereImageWriter = vtkJPEGWriter::New();<br> pSphereImageWriter->SetInput( pZImage );
<br> pSphereImageWriter->SetQuality( 40.0 );<br> pSphereImageWriter->SetFileName( strImageFile );<br> pSphereImageWriter->ProgressiveOff();<br> pSphereImageWriter->Write();<br><br>
}<br><br>void WriteWindowToImage( vtkWindow *pWindow , const char *strImageFile )<br>{<br> // write window to disk image<br> vtkWindowToImageFilter *pWindowImageFilter = vtkWindowToImageFilter::New();<br> pWindowImageFilter->SetInput( pWindow );
<br><br> vtkImageData *pImage = pWindowImageFilter->GetOutput();<br><br> vtkJPEGWriter *pSphereImageWriter = vtkJPEGWriter::New();<br> pSphereImageWriter->SetInput( pImage ); <br> pSphereImageWriter->SetQuality(
100.0 );<br> pSphereImageWriter->SetFileName( strImageFile );<br> pSphereImageWriter->ProgressiveOff();<br> pSphereImageWriter->Write();<br><br> pSphereImageWriter->Delete();<br>
pWindowImageFilter->Delete();<br>}<br><br>vtkActor *BuildSphereActor( float radius )<br>{<br> vtkSphereSource *pSphere = vtkSphereSource::New();<br> pSphere->SetCenter( 0.0 , 0.0 , 0.0 );<br>
pSphere->SetRadius( radius );<br><br> pSphere->SetStartTheta( 0.0 );<br> pSphere->SetEndTheta( 360.0 );<br> pSphere->SetThetaResolution( 30.0 );<br><br> pSphere->SetStartPhi(
0.0 );<br> pSphere->SetEndPhi( 90.0 );<br> pSphere->SetPhiResolution( 30.0 );<br><br> vtkPolyDataMapper *pSphereMapper = vtkPolyDataMapper::New(); <br> pSphereMapper->SetInput( pSphere->GetOutput() );
<br> pSphereMapper->Update();<br><br> vtkOpenGLActor *pSphereActor = vtkOpenGLActor::New();<br> pSphereActor->SetMapper( pSphereMapper ); <br><br> pSphereActor->GetProperty()->SetColor(
1.0 , 0.0 , 0.0 );<br><br> return pSphereActor;<br>}<br><br>vtkActor *BuildPlaneActor( float sphereBounds[6] )<br>{<br> vtkPolyData *pCoonsPlane = vtkPolyData::New(); <br> vtkPoints *pMeshPoints;<br>
vtkCellArray *pMeshCells;<br> <br> // allocate space for points<br> pMeshPoints = vtkPoints::New();<br> pMeshPoints->Allocate( 4 ); <br><br> pMeshPoints->InsertNextPoint( sphereBounds[0] , sphereBounds[2] ,
0.0 );<br> pMeshPoints->InsertNextPoint( sphereBounds[0] , sphereBounds[3] , 0.0 );<br> pMeshPoints->InsertNextPoint( sphereBounds[1] , sphereBounds[3] , 0.0 );<br> pMeshPoints->InsertNextPoint( sphereBounds[1] , sphereBounds[2] ,
0.0 );<br><br> // allocate space for cells<br> pMeshCells = vtkCellArray::New();<br> pMeshCells->Allocate( pMeshCells->EstimateSize( 1 , 4 ) );<br><br> vtkIdType pts[4];
<br> <br> pts[0] = 0;<br> pts[1] = 1;<br> pts[2] = 2;<br> pts[3] = 3;<br><br> pMeshCells->InsertNextCell( 4 , pts ); <br>
<br> pCoonsPlane->SetPoints( pMeshPoints );<br> pCoonsPlane->SetPolys( pMeshCells ); <br><br> pMeshPoints->Delete();<br> pMeshCells->Delete();<br><br> vtkPolyDataMapper *pCoonsMapper = vtkPolyDataMapper::New();
<br> pCoonsMapper->SetInput( pCoonsPlane );<br> pCoonsMapper->Update();<br><br> vtkOpenGLActor *pCoonsActor = vtkOpenGLActor::New();<br> pCoonsActor->SetMapper( pCoonsMapper );<br>
<br> return pCoonsActor;<br>}<br><br><br>void main()<br>{<br> // create Sphere actor first<br> float radius = 10.0;<br> vtkActor *pSphereActor = BuildSphereActor( radius );<br><br> float sphereBounds[6];
<br> pSphereActor->GetBounds( sphereBounds ); <br><br> // build coons actor<br> vtkActor *pCoonsActor = BuildPlaneActor( sphereBounds );<br><br> // setup rendering<br> vtkOpenGLRenderer *pOffScreenRenderer = vtkOpenGLRenderer::New();
<br> <br> // add actors<br> pOffScreenRenderer->AddActor( pSphereActor );<br> pOffScreenRenderer->AddActor( pCoonsActor );<br><br> // set parallel projection<br> pOffScreenRenderer->GetActiveCamera()->ParallelProjectionOn();
<br><br> double wx, wy;<br><br> wx = 500;<br> wy = 500;<br><br> vtkWin32OpenGLRenderWindow *pOffScreenRenderWindow = vtkWin32OpenGLRenderWindow::New();<br> pOffScreenRenderWindow->OffScreenRenderingOn();
<br> pOffScreenRenderWindow->AddRenderer( pOffScreenRenderer );<br> pOffScreenRenderWindow->SetSize( wx , wy );<br> pOffScreenRenderWindow->Start();<br> <br> // show only breast actor
<br> pOffScreenRenderer->Render();<br><br> // write window to disk image<br> WriteWindowToImage( pOffScreenRenderWindow , "sphere_window.jpg" );<br><br> // get Sphere zbuffer <br>
float *pSphereZBuffer = pOffScreenRenderWindow->GetZbufferData( 0 , 0 , wx , wy );<br> <br> WriteZBufferToImage( wx , wy , pSphereZBuffer , "sphere_zbuffer.jpg" );<br><br> // show only coons actor
<br> pSphereActor->VisibilityOff();<br> pOffScreenRenderer->Render();<br> <br> // write window to disk image<br> WriteWindowToImage( pOffScreenRenderWindow , "coons_window.jpg" );
<br><br> // get Sphere zbuffer <br> float *pCoonsZBuffer = pOffScreenRenderWindow->GetZbufferData( 0 , 0 , wx , wy );<br><br> // write z buffer to disk<br> WriteZBufferToImage( wx , wy , pCoonsZBuffer , "coons_zbuffer.jpg" );
<br><br> // compute diffrence<br> double dblSphereVolume = 0.0;<br><br> float clip_range[2];<br> pOffScreenRenderer->GetActiveCamera()->GetClippingRange( clip_range );<br><br> float zNear = clip_range[0];
<br> float zFar = clip_range[1];<br><br> printf( "\n zNear = %f , zFar = %f" , zNear , zFar );<br><br> for( int x = 0 ; x < wx ; x++ )<br> {<br> for( int y = 0 ; y < wy ; y++ )
<br> {<br> float coons_depth, sphere_depth;<br> long index = y * wx + x;<br><br> sphere_depth = pSphereZBuffer[index];<br> coons_depth = pCoonsZBuffer[index];
<br><br> if( !( CHECK_DEPTH( coons_depth ) && CHECK_DEPTH( sphere_depth ) ) || CHECK_DEPTH_SIMILARITY( coons_depth , sphere_depth ) )<br> continue;<br>
<br> float diff = ( coons_depth - sphere_depth );<br><br> if( diff > 0 )<br> dblSphereVolume += diff;<br> }<br> }
<br><br> float sphere_volume = ( 2 * vtkMath::Pi() / 3 ) * pow( radius , 3 );<br><br> printf( "\ncomputed Sphere volume = %f, actual sphere volume = %f\n" , dblSphereVolume , sphere_volume ); <br> getch();
<br>}</blockquote></blockquote>
<div><br> </div>