This feature prevents the camera from passing through walls or floors, making viewer manipulation much more comfortable and realistic. To use this class, first create a standard viewer and then an SoXtCollisionViewer ,SoWinCollisionViewer SoWinCollisionViewer , or SoQtCollisionViewer for this viewer. Collision detection will be activated immediately. The minimum distance between the camera and the object can be adjusted. A user callback function can be set to receive notification when a collision is detected. See SoXtCollisionViewer (or the SoQt or SoWin SoWin equivalent) for more information.
This feature is fast, even for large scenes, but only gives an approximately correct answer. Collisions are only detected “straight ahead” of the camera and some collisions may be missed if the camera is moving quickly or turning. |
Example 22.1. How to use the Collision Viewer
Source code from: $OIVHOME/src/Inventor/examples/Features/Collision/CollisionViewer/CollisionViewer.cxx
.
#include <Inventor/SoXt/viewers/SoWinCollisionViewer.h> #include <Inventor/Xt/SoXt.h> #include <Inventor/Xt/viewers/SoXtWalkViewer.h> #include <Inventor/nodes/SoCone.h> #include <Inventor/nodes/SoDirectionalLight.h> #include <Inventor/nodes/SoMaterial.h> #include <Inventor/nodes/SoPerspectiveCamera.h> #include <Inventor/nodes/SoSeparator.h> //--------------------------------------------------------------------- // Global objects SoWinCollisionViewer *collision_viewer; //--------------------------------------------------------------------- // Function declarations void onCollision(void*, SoWinCollisionViewer*); //********************************************************************* // Main function int main(int argc, char **argv) { // Window initialization -------------------------------------------- Widget myWindow = SoXt::init(argv[0]); if (myWindow == NULL) exit(1); // Which file to open ----------------------------------------------- char filename [1024]; if (argc == 1) strcpy(filename, "Barcelona.iv"); else strcpy(filename, argv[1]); // Scene graph initialization --------------------------------------- SoInput my_scene_input; if (!my_scene_input.openFile(filename)) return; SoSeparator *root = SoDB::readAll(&my_scene_input); if (root == NULL) return; my_scene_input.closeFile(); root->ref(); // Set up viewer ---------------------------------------------------- SoXtWalkViewer *my_viewer = new SoXtWalkViewer(myWindow); my_viewer->setSceneGraph(root); my_viewer->setTitle("Collision Walk Viewer"); my_viewer->show(); // Adding collision prevention -------------------------------------- collision_viewer = new SoWinCollisionViewer(my_viewer); collision_viewer->addCallback (onCollision, NULL); // Main loop -------------------------------------------------------- SoXt::show(myWindow); SoXt::mainLoop(); return 0; } //********************************************************************* // Function called when there is a collision void onCollision(void*, SoWinCollisionViewer*) { #ifdef WIN32 PlaySound("Collision.wav", NULL, SND_FILENAME + SND_ASYNC); #else printf("%c", 7); fflush(stdout); #endif }