3
votes

I am having profound issues regarding understanding the transformations involved in VTK. OpenGL has fairly good documentation and I was of the impression that VTK is verym similar to OpenGL (it is, in many ways). But when it comes to transformations, it seems to be an entirely different story.

This is a good OpenGL documentation about transforms involved: http://www.songho.ca/opengl/gl_transform.html

The perspective projection matrix in OpenGL is:

enter image description here

I wanted to see if this formula applied in VTK will give me the projection matrix of VTK (by cross-checking with VTK projection matrix).

Relevant Camera and Renderer Parameters:

camera->SetPosition(0,0,20);
camera->SetFocalPoint(0,0,0);
double crSet[2] = {10, 1000};
renderer->GetActiveCamera()->SetClippingRange(crSet);
double windowSize[2];
renderWindow->SetSize(1280,720);
renderWindowInteractor->GetSize(windowSize);
proj = renderer->GetActiveCamera()->GetProjectionTransformMatrix(windowSize[0]/windowSize[1], crSet[0], crSet[1]);

The projection transform matrix I got for this configuration is:

enter image description here

The (3,3) and (3,4) values of the projection matrix (lets say it is indexed 1 to 4 for rows and columns) should be - (f+n)/(f-n) and -2*f*n/(f-n) respectively. In my VTK camera settings, the nearz is 10 and farz is 1000 and hence I should get -1.020 and -20.20 respectively in the (3,3) and (3,4) locations of the matrix. But it is -1010 and -10000.

I have changed my clipping range values to see the changes and the (3,3) position is always nearz+farz which makes no sense to me. Also, it would be great if someone can explain why it is 3.7320 in the (1,1) and (2,2) positions. And this value DOES NOT change when I change the window size of the renderer window. Quite perplexing to me.

I see in VTKCamera class reference that GetProjectionTransformMatrix() returns the transformation matrix that maps from camera coordinates to viewport coordinates.

VTK Camera Class Reference

This is a nice depiction of the transforms involved in OpenGL rendering:

enter image description here

OpenGL Projection Matrix is the matrix that maps from eye coordinates to clip coordinates. It is beyond doubt that eye coordinates in OpenGL is the same as camera coordinates in VTK. But is the clip coordinates in OpenGL same as viewport coordinates of VTK?

My aim is to simulate a real webcam camera (already calibrated) in VTK to render a 3D model.

1

1 Answers

2
votes

Well, the documentation you linked to actually explains this (emphasis mine):

vtkCamera::GetProjectionTransformMatrix:

Return the projection transform matrix, which converts from camera coordinates to viewport coordinates. This method computes the aspect, nearz and farz, then calls the more specific signature of GetCompositeProjectionTransformMatrix

with:

vtkCamera::GetCompositeProjectionTransformMatrix:

Return the concatenation of the ViewTransform and the ProjectionTransform. This transform will convert world coordinates to viewport coordinates. The 'aspect' is the width/height for the viewport, and the nearz and farz are the Z-buffer values that map to the near and far clipping planes. The viewport coordinates of a point located inside the frustum are in the range ([-1,+1],[-1,+1], [nearz,farz]).

Note that this neither matches OpenGL's window space nor normalized device space. If find the term "viewport coordinates" for this aa poor choice, but be it as it may. What bugs me more with this is that the matrix actually does not transform to that "viewport space", but to some clip-space equivalent. Only after the perspective divide, the coordinates will be in the range as given for the above definition of the "viewport space".

But is the clip coordinates in OpenGL same as viewport coordinates of VTK?

So that answer is a clear no. But it is close. Basically, that projection matrix is just a scaled and shiftet along the z dimension, and it is easy to convert between those two. Basically, you can simply take znear and zfar out of VTK's matrix, and put it into that OpenGL projection matrix formula you linked above, replacing just those two matrix elements.