root/OpenSceneGraph/trunk/examples/osgkeyboardmouse/osgkeyboardmouse.cpp @ 2540

Revision 2540, 9.1 kB (checked in by robert, 11 years ago)

Added two news examples, osgsimple just loads a model and then renders it in
a single window. osgkeyboardmouse adds to osgsimple support for keyboard mouse
and picking interactions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// C++ source file - (C) 2003 Robert Osfield, released under the OSGPL.
2//
3// Simple example of use of Producer::RenderSurface + KeyboardMouseCallback + SceneView
4// example that provides the user with control over view position with basic picking.
5
6#include <Producer/RenderSurface>
7#include <Producer/KeyboardMouse>
8#include <Producer/Trackball>
9
10#include <osg/Timer>
11
12#include <osgUtil/SceneView>
13#include <osgUtil/IntersectVisitor>
14
15#include <osgDB/ReadFile>
16
17#include <osgFX/Scribe>
18
19
20class MyKeyboardMouseCallback : public Producer::KeyboardMouseCallback
21{
22public:
23
24    MyKeyboardMouseCallback(osgUtil::SceneView* sceneView) :
25        Producer::KeyboardMouseCallback(),
26        _mx(0.0f),_my(0.0f),_mbutton(0),
27        _done(false),
28        _trackBall(new Producer::Trackball),
29        _sceneView(sceneView)
30    {
31        resetTrackball();
32        _mouseMovingOnPreviousRelease = false;
33    }
34
35    virtual void specialKeyPress( Producer::KeyCharacter key )
36    {
37        if (key==Producer::KeyChar_Escape)
38                    shutdown();
39    }
40
41    virtual void shutdown()
42    {
43        _done = true;
44    }
45
46    virtual void keyPress( Producer::KeyCharacter key)
47    {
48        if (key==' ') resetTrackball();
49    }
50
51    virtual void mouseMotion( float mx, float my )
52    {
53        _mx = mx;
54        _my = my;
55    }
56
57    virtual void buttonPress( float mx, float my, unsigned int mbutton )
58    {
59         _mx = mx;
60         _my = my;
61         _mbutton |= (1<<(mbutton-1));
62         
63         _mx_buttonPress = _mx;
64         _my_buttonPress = _my;
65    }
66    virtual void buttonRelease( float mx, float my, unsigned int mbutton )
67    {
68        _mx = mx;
69        _my = my;
70        _mbutton &= ~(1<<(mbutton-1));
71       
72        if (_mx==_mx_buttonPress && _my_buttonPress==_my)
73        {
74            if (!_mouseMovingOnPreviousRelease)
75            {
76                // button press and release without moving so assume this means
77                // the users wants to pick.
78                pick(_mx,_my);
79            }
80            _mouseMovingOnPreviousRelease = false;
81        }
82        else
83        {
84            _mouseMovingOnPreviousRelease = true;
85        }
86    }
87
88    bool done() { return _done; }
89    float mx()  { return _mx; }
90    float my()  { return _my; }
91    unsigned int mbutton()  { return _mbutton; }
92   
93    void resetTrackball()
94    {
95        osg::Node* scene = _sceneView->getSceneData();
96        if (scene)
97        {
98            const osg::BoundingSphere& bs = scene->getBound();
99            _trackBall->reset();
100            _trackBall->setOrientation( Producer::Trackball::Z_UP );
101            _trackBall->setDistance(bs.radius()*2.0f);
102            _trackBall->translate(-bs.center().x(),-bs.center().y(),-bs.center().z());
103        }
104    }
105   
106    osg::Matrixd getViewMatrix()
107    {
108        _trackBall->input( mx(), my(), mbutton() );
109        return osg::Matrixd(_trackBall->getMatrix().ptr());
110    }
111   
112    void pick(float x, float y)
113    {
114        osg::Node* scene = _sceneView->getSceneData();
115        if (scene)
116        {
117            std::cout<<"Picking "<<x<<"\t"<<y<<std::endl;
118
119
120            int origX, origY, width, height;
121            _sceneView->getViewport(origX,origY,width,height);
122
123            // convert Produce's non dimensional x,y coords back into pixel coords.
124            int winX = (int)((x+1.0f)*0.5f*(float)width);
125            int winY = (int)((y+1.0f)*0.5f*(float)height);
126
127            osg::Vec3 nearPoint, farPoint;
128            _sceneView->projectWindowXYIntoObject(winX,winY,nearPoint,farPoint);
129
130            std::cout<<"nearPoint "<<nearPoint<<"  farPoint "<<farPoint<<std::endl;
131
132            // make a line segment
133            osg::ref_ptr<osg::LineSegment> lineSegment = new osg::LineSegment(nearPoint,farPoint);
134
135            // create the IntersectVisitor to do the line intersection traversals.
136            osgUtil::IntersectVisitor intersector;
137            intersector.addLineSegment(lineSegment.get());
138           
139            scene->accept(intersector);
140           
141            osgUtil::IntersectVisitor::HitList& hits=intersector.getHitList(lineSegment.get());
142            if (!hits.empty())
143            {
144                std::cout<<"Got hits"<<std::endl;
145               
146                // just take the first hit - nearest the eye point.
147                osgUtil::Hit& hit = hits.front();
148               
149                osg::NodePath& nodePath = hit._nodePath;
150                osg::Node* node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0;
151                osg::Group* parent = (nodePath.size()>=2)?dynamic_cast<osg::Group*>(nodePath[nodePath.size()-2]):0;
152               
153                if (parent && node)
154                {
155               
156                    std::cout<<"Hits "<<node->className()<<std::endl;
157                    std::cout<<" parent "<<parent->className()<<std::endl;
158                   
159                    osgFX::Scribe* parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent);
160                    if (!parentAsScribe)
161                    {
162                        // node not already picked, so highlight it with an osgFX::Scribe
163                        osgFX::Scribe* scribe = new osgFX::Scribe();
164                        scribe->addChild(node);
165                        parent->replaceChild(node,scribe);
166                    }
167                    else
168                    {
169                        // node already picked so we want to remove scribe to unpick it.
170                        osg::Node::ParentList parentList = parentAsScribe->getParents();
171                        for(osg::Node::ParentList::iterator itr=parentList.begin();
172                            itr!=parentList.end();
173                            ++itr)
174                        {
175                            (*itr)->replaceChild(parentAsScribe,node);
176                        }
177                    }
178                }
179
180            }
181           
182        }       
183       
184    }
185
186private:
187
188    float                               _mx, _my;
189    float                               _mx_buttonPress, _my_buttonPress;
190    unsigned int                        _mbutton;
191    bool                                _mouseMovingOnPreviousRelease;
192   
193    bool                                _done;
194   
195    osg::ref_ptr<Producer::Trackball>   _trackBall;
196    osg::ref_ptr<osgUtil::SceneView>    _sceneView;
197};
198
199int main( int argc, char **argv )
200{
201    if (argc<2)
202    {
203        std::cout << argv[0] <<": requires filename argument." << std::endl;
204        return 1;
205    }
206
207    // load the scene.
208    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(argv[1]);
209    if (!loadedModel)
210    {
211        std::cout << argv[0] <<": No data loaded." << std::endl;
212        return 1;
213    }
214   
215    // create the window to draw to.
216    osg::ref_ptr<Producer::RenderSurface> renderSurface = new Producer::RenderSurface;
217    renderSurface->setWindowName("osgsimple");
218    renderSurface->setWindowRectangle(100,100,800,600);
219    renderSurface->useBorder(true);
220    renderSurface->realize();
221   
222
223    // create the view of the scene.
224    osg::ref_ptr<osgUtil::SceneView> sceneView = new osgUtil::SceneView;
225    sceneView->setDefaults();
226    sceneView->setSceneData(loadedModel.get());
227
228
229    // set up a KeyboardMouse to manage the events comming in from the RenderSurface
230    osg::ref_ptr<Producer::KeyboardMouse>  kbm = new Producer::KeyboardMouse(renderSurface.get());
231
232    // create a KeyboardMouseCallback to handle the mouse events within this applications
233    osg::ref_ptr<MyKeyboardMouseCallback> kbmcb = new MyKeyboardMouseCallback(sceneView.get());
234
235
236    // record the timer tick at the start of rendering.   
237    osg::Timer_t start_tick = osg::Timer::instance()->tick();
238   
239    unsigned int frameNum = 0;
240
241    // main loop (note, window toolkits which take control over the main loop will require a window redraw callback containing the code below.)
242    while( renderSurface->isRealized() && !kbmcb->done())
243    {
244        // set up the frame stamp for current frame to record the current time and frame number so that animtion code can advance correctly
245        osg::FrameStamp* frameStamp = new osg::FrameStamp;
246        frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(start_tick,osg::Timer::instance()->tick()));
247        frameStamp->setFrameNumber(frameNum++);
248       
249        // pass frame stamp to the SceneView so that the update, cull and draw traversals all use the same FrameStamp
250        sceneView->setFrameStamp(frameStamp);
251
252        // pass any keyboard mouse events onto the local keyboard mouse callback.       
253        kbm->update( *kbmcb );
254       
255        // set the view
256        sceneView->setViewMatrix(kbmcb->getViewMatrix());
257
258        // update the viewport dimensions, incase the window has been resized.
259        sceneView->setViewport(0,0,renderSurface->getWindowWidth(),renderSurface->getWindowHeight());
260
261        // do the update traversal the scene graph - such as updating animations
262        sceneView->update();
263       
264        // do the cull traversal, collect all objects in the view frustum into a sorted set of rendering bins
265        sceneView->cull();
266       
267        // draw the rendering bins.
268        sceneView->draw();
269
270        // Swap Buffers
271        renderSurface->swapBuffers();
272    }
273
274    return 0;
275}
Note: See TracBrowser for help on using the browser.