1 // OpenSG Tutorial Example: Picking
3 // In addition to the loading example this one shows how to pick an object.
5 // To do that the IntersectAction is introduced, which tests rays against
8 // Use Space to send a ray into the scene. If it hits something the hit
9 // triangle will be highlighted.
12 #ifdef OSG_BUILD_ACTIVE
15 #include <OSGConfig.h>
16 #include <OSGSimpleGeometry.h>
17 #include <OSGGeoProperties.h>
18 #include <OSGGLUTWindow.h>
19 #include <OSGSimpleSceneManager.h>
20 #include <OSGAction.h>
22 #include <OSGSceneFileHandler.h>
23 #include <OSGTriangleIterator.h>
27 // the ray intersect traversal
28 #include <OSGIntersectAction.h>
31 #include <OpenSG/OSGGLUT.h>
32 #include <OpenSG/OSGConfig.h>
33 #include <OpenSG/OSGSimpleGeometry.h>
34 #include <OpenSG/OSGGeoProperties.h>
35 #include <OpenSG/OSGGLUTWindow.h>
36 #include <OpenSG/OSGSimpleSceneManager.h>
37 #include <OpenSG/OSGAction.h>
38 #include <OpenSG/OSGGroup.h>
39 #include <OpenSG/OSGSceneFileHandler.h>
40 #include <OpenSG/OSGTriangleIterator.h>
44 // the ray intersect traversal
45 #include <OpenSG/OSGIntersectAction.h>
49 // The SimpleSceneManager to manage simple applications
50 OSG::SimpleSceneManagerRefPtr mgr
;
52 // The file root node, needed for intersection
53 OSG::NodeRefPtr fileroot
;
55 // The points used for visualising the ray and hit object
56 OSG::GeoPnt3fPropertyRefPtr isectPoints
;
58 // The visualisation geometry, needed for update.
59 OSG::GeometryRefPtr testgeocore
;
61 // forward declaration so we can have the interesting stuff upfront
62 int setupGLUT( int *argc
, char *argv
[] );
65 void keyboard(unsigned char k
, int x
, int y
)
71 // clean up global variables
82 case ' ': // send a ray through the clicked pixel
84 Intersection testing for rays is done using an
85 IntersectAction. The ray itself is calculated by the
86 SimpleSceneManager, given the clicked pixel.
88 It needs to be set up with the line that is to be
89 intersected. A line is a semi-infinite ray which has a
90 starting point and a direction, and extends in the
91 direction to infinity.
93 To do the actual test the Action's apply() method is used.
95 The results can be received from the Action. The main
96 difference is if something was hit or not, which is
99 If an intersection did occur, the other data elements are
100 valid, otherwise they are undefined.
102 The information that is stored in the action is the object
103 which was hit, the triangle of the object that was hit (in
104 the form of its index) and the actual hit position.
109 l
= mgr
->calcViewRay(x
, y
);
111 std::cerr
<< "From " << l
.getPosition ()
112 << ", dir " << l
.getDirection() << std::endl
;
114 OSG::IntersectActionRefPtr act
= OSG::IntersectAction::create();
117 act
->apply(fileroot
);
119 isectPoints
->setValue(l
.getPosition(), 0);
120 isectPoints
->setValue(l
.getPosition() + l
.getDirection(), 1);
122 // did we hit something?
125 // yes!! print and highlight it
126 std::cerr
<< " object " << act
->getHitObject ()
127 << " tri " << act
->getHitTriangle()
128 << " at " << act
->getHitPoint ();
130 mgr
->setHighlight(act
->getHitObject());
132 // stop the ray on the hit surface
133 isectPoints
->setValue(l
.getPosition() +
134 l
.getDirection() * act
->getHitT(), 1);
136 // find the triangle that was hit
137 OSG::TriangleIterator
it(act
->getHitObject());
138 it
.seek(act
->getHitTriangle());
140 // calculate its vertex positions in world space
142 act
->getHitObject()->getToWorld(m
);
144 // and turn them into a triangle
145 OSG::Pnt3f p
= it
.getPosition(0);
147 isectPoints
->setValue(p
, 2);
148 p
= it
.getPosition(1);
150 isectPoints
->setValue(p
, 3);
151 p
= it
.getPosition(2);
153 isectPoints
->setValue(p
, 4);
157 // no, get rid of the triangle and highlight.
158 isectPoints
->setValue(OSG::Pnt3f(0,0,0), 2);
159 isectPoints
->setValue(OSG::Pnt3f(0,0,0), 3);
160 isectPoints
->setValue(OSG::Pnt3f(0,0,0), 4);
162 mgr
->setHighlight(NULL
);
165 OSG::commitChanges();
170 std::cerr
<< std::endl
;
178 mgr
->setStatistics(!mgr
->getStatistics());
184 // Initialize GLUT & OpenSG and set up the scene
185 int main(int argc
, char **argv
)
188 OSG::osgInit(argc
,argv
);
191 int winid
= setupGLUT(&argc
, argv
);
193 // open a new scope, because the pointers below should go out of scope
194 // before entering glutMainLoop.
195 // Otherwise OpenSG will complain about objects being alive after shutdown.
197 // the connection between GLUT and OpenSG
198 OSG::GLUTWindowRefPtr gwin
= OSG::GLUTWindow::create();
199 gwin
->setGlutId(winid
);
204 OSG::NodeRefPtr scene
= OSG::Node::create();
205 OSG::GroupRefPtr g
= OSG::Group::create();
211 FWARNING(("No file given!\n"));
212 FWARNING(("Supported file formats:\n"));
214 std::list
<const char*> suffixes
;
215 OSG::SceneFileHandler::the()->getSuffixList(suffixes
);
217 for(std::list
<const char*>::iterator it
= suffixes
.begin();
218 it
!= suffixes
.end();
221 FWARNING(("%s\n", *it
));
224 fileroot
= OSG::makeTorus(.5, 2, 16, 16);
229 All scene file loading is handled via the SceneFileHandler.
231 fileroot
= OSG::SceneFileHandler::the()->read(argv
[1]);
234 scene
->addChild(fileroot
);
236 // Create a small geometry to show the ray and what was hit
237 // Contains a line and a single triangle.
238 // The line shows the ray, the triangle whatever was hit.
240 OSG::SimpleMaterialRefPtr red
= OSG::SimpleMaterial::create();
242 red
->setDiffuse (OSG::Color3f( 1,0,0 ));
243 red
->setTransparency(0.5);
246 isectPoints
= OSG::GeoPnt3fProperty::create();
247 isectPoints
->addValue(OSG::Pnt3f(0,0,0));
248 isectPoints
->addValue(OSG::Pnt3f(0,0,0));
249 isectPoints
->addValue(OSG::Pnt3f(0,0,0));
250 isectPoints
->addValue(OSG::Pnt3f(0,0,0));
251 isectPoints
->addValue(OSG::Pnt3f(0,0,0));
253 OSG::GeoUInt32PropertyRefPtr index
= OSG::GeoUInt32Property::create();
260 OSG::GeoUInt32PropertyRefPtr lens
= OSG::GeoUInt32Property::create();
264 OSG::GeoUInt8PropertyRefPtr type
= OSG::GeoUInt8Property::create();
265 type
->addValue(GL_LINES
);
266 type
->addValue(GL_TRIANGLES
);
268 testgeocore
= OSG::Geometry::create();
269 testgeocore
->setPositions(isectPoints
);
270 testgeocore
->setIndices(index
);
271 testgeocore
->setLengths(lens
);
272 testgeocore
->setTypes(type
);
273 testgeocore
->setMaterial(red
);
275 OSG::NodeRefPtr testgeo
= OSG::Node::create();
276 testgeo
->setCore(testgeocore
);
278 scene
->addChild(testgeo
);
280 OSG::commitChanges();
282 // create the SimpleSceneManager helper
283 mgr
= OSG::SimpleSceneManager::create();
285 // tell the manager what to manage
286 mgr
->setWindow(gwin
);
287 mgr
->setRoot (scene
);
289 // show the whole scene
300 // GLUT callback functions
309 // react to size changes
310 void reshape(int w
, int h
)
316 // react to mouse button presses
317 void mouse(int button
, int state
, int x
, int y
)
320 mgr
->mouseButtonRelease(button
, x
, y
);
322 mgr
->mouseButtonPress(button
, x
, y
);
327 // react to mouse motions with pressed buttons
328 void motion(int x
, int y
)
330 mgr
->mouseMove(x
, y
);
334 // setup the GLUT library which handles the windows for us
335 int setupGLUT(int *argc
, char *argv
[])
337 glutInit(argc
, argv
);
338 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
340 int winid
= glutCreateWindow("OpenSG");
342 glutReshapeFunc(reshape
);
343 glutDisplayFunc(display
);
344 glutMouseFunc(mouse
);
345 glutMotionFunc(motion
);
346 glutKeyboardFunc(keyboard
);