I tried to set up a scene with reverse perspective viewing geometry, where the projection rays converge "behind" the scene. I used the normal SoPerspectiveCamera, but changed
- the position (moved along the projection direction to a point behind the scene)
- near, far and focal distance (set to negative values to set up a view frustum "behind" the camera)
- orientation (rotated camera by 180 degree around the z axis to compensate the image flip induced by the negative near distance)
Example: Scene with cube at origin
- position: 0 0 10
- orientation: 0 0 1 0
- nearDistance: 1
- farDistance: 20
- focalDistance: 10
Reverse perspective camera:
- position: 0 0 -10
- orientation: 0 0 1 3.14159
- nearDistance: -20
- farDistance: -1
- focalDistance: -10
Only one small change to function get_perspective_projection() in SbDPViewVolume.cpp was necessary to render the scene with reverse perspective viewing geometry. Since OpenGL clips in homogeneous space (before computing the perspective division), it assumes that the homogeneous w coordinate in clip space is positive. With the reversed setup, the scene is on the positive z axis of the camera coordinate system, thus the w coordinate in clip space is negative when using the standard OpenGL projection matrix. This can be compensated by multiplying the whole projection matrix by -1 if the near distance is negative.
With this change, the scene is rendered with the expected viewing geometry (see attached images and scene graph). The render state is also set up in a convenient manner, e.g.
- the view volume direction points from scene foreground to background
- the camera space orientation (after applying the viewing matrix) is consistent with the normal perspective case (negative z axis points from foreground to background, y axis points upwards), so lighting also works fine
- the world space picking ray points from scene foreground to background
By changing 3 more lines of code (functions SbProjector::verifyProjection(), SbSphereProjector::isPointInFront() and SbCylinderProjector::isPointInFront) at least the standard manipulators (TrackballManip, TransformBoxManip) are also working nicely with reverse perspective viewing geometry.
I can provide my changes on a forked branch. It would be great, if Coin would support reverse perspective projections by merging them to the main branch.