root/branches/Dirk_CPtr/Tutorials/11picking.cpp

Revision 637, 9.2 kB (checked in by vossg, 2 years ago)

fixed : added statistics key (s)

  • Property svn:eol-style set to native
Line 
1 // OpenSG Tutorial Example: Picking
2 //
3 // In addition to the loading example this one shows how to pick an object.
4 //
5 // To do that the IntersectAction is introduced, which tests rays against
6 // geometry.
7 //
8 // Use Space to send a ray into the scene. If it hits something the hit
9 // triangle will be highlighted.
10 //
11
12 // Headers
13 #include <OpenSG/OSGGLUT.h>
14 #include <OpenSG/OSGConfig.h>
15 #include <OpenSG/OSGSimpleGeometry.h>
16 #include <OpenSG/OSGGeoProperties.h>
17 #include <OpenSG/OSGGLUTWindow.h>
18 #include <OpenSG/OSGSimpleSceneManager.h>
19 #include <OpenSG/OSGAction.h>
20 #include <OpenSG/OSGGroup.h>
21 #include <OpenSG/OSGSceneFileHandler.h>
22 #include <OpenSG/OSGTriangleIterator.h>
23
24 // New Headers
25
26 // the ray intersect traversal
27 #include <OpenSG/OSGIntersectAction.h>
28
29
30 // Activate the OpenSG namespace
31 OSG_USING_NAMESPACE
32
33 // The SimpleSceneManager to manage simple applications
34 SimpleSceneManager *mgr;
35
36 // The file root node, needed for intersection
37 NodePtr fileroot;
38
39 // The points used for visualising the ray and hit object
40 GeoPnt3fPropertyPtr isectPoints;
41
42 // The visualisation geometry, needed for update.
43 GeometryPtr testgeocore;
44
45 // forward declaration so we can have the interesting stuff upfront
46 int setupGLUT( int *argc, char *argv[] );
47
48 // react to keys
49 void keyboard(unsigned char k, int x, int y)
50 {
51     switch(k)
52     {
53         case 27:   
54         {
55             OSG::osgExit();
56             exit(0);
57         }
58         break;
59
60         case ' ':   // send a ray through the clicked pixel
61                 /*
62                     Intersection testing for rays is done using an
63                     IntersectAction. The ray itself is calculated by the
64                     SimpleSceneManager, given the clicked pixel.
65                     
66                     It needs to be set up with the line that is to be
67                     intersected. A line is a semi-infinite ray which has a
68                     starting point and a direction, and extends in the
69                     direction to infinity.
70                     
71                     To do the actual test the Action's apply() method is used.
72                     
73                     The results can be received from the Action. The main
74                     difference is if something was hit or not, which is
75                     returned in didHit().
76                     
77                     If an intersection did occur, the other data elements are
78                     valid, otherwise they are undefined.
79                     
80                     The information that is stored in the action is the object
81                     which was hit, the triangle of the object that was hit (in
82                     the form of its index) and the actual hit position.             
83                 */
84                 {
85                 Line l;
86                
87                 l = mgr->calcViewRay(x, y);
88
89                 std::cerr << "From "  << l.getPosition ()
90                           << ", dir " << l.getDirection() << std::endl;
91    
92                 IntersectAction *act = IntersectAction::create();
93                
94                 act->setLine(l);
95                 act->apply(fileroot);
96            
97                 isectPoints->setValue(l.getPosition(), 0);
98                 isectPoints->setValue(l.getPosition() + l.getDirection(), 1);
99            
100                 // did we hit something?
101                 if (act->didHit())
102                 {
103                     // yes!! print and highlight it
104                     std::cerr << " object " << act->getHitObject  ()
105                               << " tri "    << act->getHitTriangle()
106                               << " at "     << act->getHitPoint   ();
107                    
108                     mgr->setHighlight(act->getHitObject());
109                    
110                     // stop the ray on the hit surface
111                     isectPoints->setValue(l.getPosition() +
112                             l.getDirection() * act->getHitT(), 1);
113                    
114                     // find the triangle that was hit
115                     TriangleIterator it(act->getHitObject());
116                     it.seek(act->getHitTriangle());
117                    
118                     // calculate its vertex positions in world space
119                     Matrix m;
120                     act->getHitObject()->getToWorld(m);
121            
122                     // and turn them into a triangle
123                     Pnt3f p = it.getPosition(0);
124                     m.multMatrixPnt(p);
125                     isectPoints->setValue(p, 2);
126                     p = it.getPosition(1);
127                     m.multMatrixPnt(p);
128                     isectPoints->setValue(p, 3);
129                     p = it.getPosition(2);
130                     m.multMatrixPnt(p);
131                     isectPoints->setValue(p, 4);
132                 }
133                 else
134                 {
135                     // no, get rid of the triangle and highlight.
136                     isectPoints->setValue(Pnt3f(0,0,0), 2);
137                     isectPoints->setValue(Pnt3f(0,0,0), 3);
138                     isectPoints->setValue(Pnt3f(0,0,0), 4);
139                    
140                     mgr->setHighlight(NullFC);
141                 }
142
143                 commitChanges();
144            
145                 // free the action
146                 delete act;
147                
148                 std::cerr << std::endl;
149                
150                 glutPostRedisplay();           
151                 }
152                 break;
153
154         case 's':
155         {
156             mgr->setStatistics(!mgr->getStatistics());
157         }
158         break;
159     }
160 }
161
162 // Initialize GLUT & OpenSG and set up the scene
163 int main(int argc, char **argv)
164 {
165     // OSG init
166     osgInit(argc,argv);
167
168     // GLUT init
169     int winid = setupGLUT(&argc, argv);
170
171     // the connection between GLUT and OpenSG
172     GLUTWindowPtr gwin= GLUTWindow::create();
173     gwin->setId(winid);
174     gwin->init();
175
176     // The scene group
177     
178     NodePtr  scene = Node::create();
179     GroupPtr g     = Group::create();
180    
181     scene->setCore(g);
182    
183     if(argc < 2)
184     {
185         FWARNING(("No file given!\n"));
186         FWARNING(("Supported file formats:\n"));
187        
188         std::list<const char*> suffixes;
189         SceneFileHandler::the()->getSuffixList(suffixes);
190        
191         for(std::list<const char*>::iterator it  = suffixes.begin();
192                                              it != suffixes.end();
193                                            ++it)
194         {
195             FWARNING(("%s\n", *it));
196         }
197
198         fileroot = makeTorus(.5, 2, 16, 16);
199     }
200     else
201     {
202         /*
203             All scene file loading is handled via the SceneFileHandler.
204         */
205         fileroot = SceneFileHandler::the()->read(argv[1]);
206     }
207
208     scene->addChild(fileroot);
209    
210     // Create a small geometry to show the ray and what was hit
211     // Contains a line and a single triangle.
212     // The line shows the ray, the triangle whatever was hit.
213     
214     SimpleMaterialPtr red = SimpleMaterial::create();
215    
216     red->setDiffuse     (Color3f( 1,0,0 ));   
217     red->setTransparency(0.5);   
218     red->setLit         (false);   
219
220     isectPoints = GeoPnt3fProperty::create();
221     isectPoints->addValue(Pnt3f(0,0,0));
222     isectPoints->addValue(Pnt3f(0,0,0));
223     isectPoints->addValue(Pnt3f(0,0,0));
224     isectPoints->addValue(Pnt3f(0,0,0));
225     isectPoints->addValue(Pnt3f(0,0,0));
226
227     GeoUInt32PropertyPtr index = GeoUInt32Property::create();
228     index->addValue(0);
229     index->addValue(1);
230     index->addValue(2);
231     index->addValue(3);
232     index->addValue(4);
233
234     GeoUInt32PropertyPtr lens = GeoUInt32Property::create();
235     lens->addValue(2);
236     lens->addValue(3);
237    
238     GeoUInt8PropertyPtr type = GeoUInt8Property::create();
239     type->addValue(GL_LINES);
240     type->addValue(GL_TRIANGLES);
241
242     testgeocore = Geometry::create();
243     testgeocore->setPositions(isectPoints);
244     testgeocore->setIndices(index);
245     testgeocore->setLengths(lens);
246     testgeocore->setTypes(type);
247     testgeocore->setMaterial(red);
248    
249     NodePtr testgeo = Node::create();
250     testgeo->setCore(testgeocore);
251    
252     scene->addChild(testgeo);
253
254     commitChanges();
255
256     // create the SimpleSceneManager helper
257     mgr = new SimpleSceneManager;
258
259     // tell the manager what to manage
260     mgr->setWindow(gwin );
261     mgr->setRoot  (scene);
262
263     // show the whole scene
264     mgr->showAll();
265
266     // GLUT main loop
267     glutMainLoop();
268
269     return 0;
270 }
271
272 //
273 // GLUT callback functions
274 //
275
276 // redraw the window
277 void display(void)
278 {
279     mgr->redraw();
280 }
281
282 // react to size changes
283 void reshape(int w, int h)
284 {
285     mgr->resize(w, h);
286     glutPostRedisplay();
287 }
288
289 // react to mouse button presses
290 void mouse(int button, int state, int x, int y)
291 {
292     if (state)
293         mgr->mouseButtonRelease(button, x, y);
294     else
295         mgr->mouseButtonPress(button, x, y);
296        
297     glutPostRedisplay();
298 }
299
300 // react to mouse motions with pressed buttons
301 void motion(int x, int y)
302 {
303     mgr->mouseMove(x, y);
304     glutPostRedisplay();
305 }
306
307 // setup the GLUT library which handles the windows for us
308 int setupGLUT(int *argc, char *argv[])
309 {
310     glutInit(argc, argv);
311     glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
312    
313     int winid = glutCreateWindow("OpenSG");
314    
315     glutReshapeFunc(reshape);
316     glutDisplayFunc(display);
317     glutMouseFunc(mouse);
318     glutMotionFunc(motion);
319     glutKeyboardFunc(keyboard);
320
321     return winid;
322 }
Note: See TracBrowser for help on using the browser.