coin3d / coin

Coin3D core library
BSD 3-Clause "New" or "Revised" License
280 stars 106 forks source link

Add support for reverse perspective rendering #80

Closed VolkerEnderlein closed 9 years ago

VolkerEnderlein commented 9 years ago

Original report by Mario Koerner (Bitbucket: Renreok, GitHub: Renreok).

Attachments: Perspective.jpg | ReversePerspective.jpg | ReversePerspectiveCube.iv


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

Example: Scene with cube at origin

Perspective camera:

Reverse perspective camera:

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.

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.

VolkerEnderlein commented 9 years ago

Original comment by Thomas Moeller (Bitbucket: TheHubbit, GitHub: TheHubbit).


Mario,

Thank you for the enhancement proposal and the detailed description. I support this idea. But can you please add some code snippets or a diff file? There doesn't seem to be a Coin fork in your repositories.

Thank you,

Thomas

VolkerEnderlein commented 9 years ago

Original comment by Roy Walmsley (Bitbucket: walroy, GitHub: walroy).


Mario,

I too support this idea. Can you also bear in mind that there should be some documentation comments, particularly with respect to describing the basic camera setup required (as you have done above) to achieve this. The top of the SoPerspectiveCamera.cpp file would seem to be the best place.

Now I have been looking at this some more and wondering ...

How it might be implemented for VRML (and my extensions to X3D). In VRML there is the Viewpoint node. X3D has the Viewpoint and OrthoViewpoint nodes. None of them has support for setting anything other than the position, orientation and field of view of the cameras.

Should we introduce a new node - SoReversePersepctiveCamera (perhaps derived from SoPerspectiveCamera) with the defaults modified for the field settings.

Comments please.

Roy

VolkerEnderlein commented 9 years ago

Original comment by Mario Koerner (Bitbucket: Renreok, GitHub: Renreok).


Hi Thomas and Roy,

I will commit my changes and create a pull request as soon as I find some time. I will also add documentation to SoPerspectiveCamera.cpp.

Roy: I think it would be possible to derive a SoReversePerspectiveCamera class from SoPerspectiveCamera. It should be sufficient to override the getViewVolume() function that derives the view volume as already sketched in my original post:

RevPerspCam.jpg

#!c++
vv.position = cam.position + (cam.nearDist + cam.farDist) * cam.direction
vv.orientation = cam.orientation * rotation(0 0 1 pi)
vv.nearDist = -cam.farDist
vv.farDist = -cam.nearDist
vv.focalDist = cam.focalDist - (cam.nearDist + cam.farDist)

With that setup, one could just copy the field values from a normal perspective camera to a reverse perspective camera. It would also be possible to cast a SoReversePerspectiveCamera instance to SoPerspectiveCamera and handle it as a normal camera.

What do you think? Would this solve your issue with the VRML viewpoints?

Best, Mario

VolkerEnderlein commented 9 years ago

Original comment by Roy Walmsley (Bitbucket: walroy, GitHub: walroy).


Hi Mario,

Thanks for the update. In some ways I like the idea of the SoReversePerspectiveCamera class. However, I need to look at all the changes you have mentioned above and see what the implications are.

With respect to VRML this would tie in then with the possibility of adding a SoVRMLReversePerspectiveViewpoint node. A similar extension could be proposed for X3D then.

Roy

VolkerEnderlein commented 9 years ago

Original comment by Roy Walmsley (Bitbucket: walroy, GitHub: walroy).


Completed on pull request #210