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

Revision 1039, 9.3 kB (checked in by cneumann, 11 months ago)

changed: - factory functions return a TransitPtr? that can not be implicitly

converted to C Ptr. Should help with porting.

added: - GlobalRefPtr?, needed for cases where upon return from main

a RefPtr? goes out of scope (it would attempt to access the
FCFactory which is already shutdown at that point).

status: - vrml loader does not compile (needs porting to ref ptr)

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