root/OpenSceneGraph/trunk/examples/osghangglide/GliderManipulator.cpp @ 6941

Revision 6941, 8.2 kB (checked in by robert, 7 years ago)

From Martin Lavery and Robert Osfield, Updated examples to use a variation of the MIT License

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osghangglide.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include "GliderManipulator.h"
20#include <osg/Notify>
21
22using namespace osg;
23using namespace osgGA;
24
25GliderManipulator::GliderManipulator()
26{
27    _modelScale = 0.01f;
28    _velocity = 0.2f;
29    _yawMode = YAW_AUTOMATICALLY_WHEN_BANKED;
30
31    _distance = 1.0f;
32}
33
34
35GliderManipulator::~GliderManipulator()
36{
37}
38
39
40void GliderManipulator::setNode(osg::Node* node)
41{
42    _node = node;
43    if (_node.get())
44    {
45        const osg::BoundingSphere& boundingSphere=_node->getBound();
46        _modelScale = boundingSphere._radius;
47    }
48}
49
50
51const osg::Node* GliderManipulator::getNode() const
52{
53    return _node.get();
54}
55
56
57
58osg::Node* GliderManipulator::getNode()
59{
60    return _node.get();
61}
62
63void GliderManipulator::home(const GUIEventAdapter& ea,GUIActionAdapter& us)
64{
65    if(_node.get())
66    {
67
68        const osg::BoundingSphere& boundingSphere=_node->getBound();
69
70        osg::Vec3 eye = boundingSphere._center+osg::Vec3(-boundingSphere._radius*0.25f,-boundingSphere._radius*0.25f,-boundingSphere._radius*0.03f);
71
72        computePosition(eye,
73            osg::Vec3(1.0f,1.0f,-0.1f),
74            osg::Vec3(0.0f,0.0f,1.0f));
75
76        _velocity = boundingSphere._radius*0.01f;
77
78        us.requestRedraw();
79
80        us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2.0f,(ea.getYmin()+ea.getYmax())/2.0f);
81
82        flushMouseEventStack();
83
84    }
85
86}
87
88
89void GliderManipulator::init(const GUIEventAdapter& ea,GUIActionAdapter& us)
90{
91    flushMouseEventStack();
92
93    us.requestContinuousUpdate(false);
94
95    _velocity = 0.2f;
96
97    if (ea.getEventType()!=GUIEventAdapter::RESIZE)
98    {
99        us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2.0f,(ea.getYmin()+ea.getYmax())/2.0f);
100    }
101}
102
103
104bool GliderManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
105{
106    switch(ea.getEventType())
107    {
108#if 0   
109        case(GUIEventAdapter::PUSH):
110        {
111
112            addMouseEvent(ea);
113            us.requestContinuousUpdate(true);
114            if (calcMovement()) us.requestRedraw();
115            return true;
116        }
117
118        case(GUIEventAdapter::RELEASE):
119        {
120
121            addMouseEvent(ea);
122            us.requestContinuousUpdate(true);
123            // if (calcMovement()) us.requestRedraw();
124            return true;
125        }
126
127        case(GUIEventAdapter::DRAG):
128        {
129
130            addMouseEvent(ea);
131            us.requestContinuousUpdate(true);
132            // if (calcMovement()) us.requestRedraw();
133            return true;
134        }
135
136        case(GUIEventAdapter::MOVE):
137        {
138
139            addMouseEvent(ea);
140            us.requestContinuousUpdate(true);
141            // if (calcMovement()) us.requestRedraw();
142
143            return true;
144        }
145#endif
146        case(GUIEventAdapter::KEYDOWN):
147            if (ea.getKey()==' ')
148            {
149                flushMouseEventStack();
150                home(ea,us);
151                us.requestRedraw();
152                us.requestContinuousUpdate(false);
153                return true;
154            }
155            else if (ea.getKey()=='q')
156            {
157                _yawMode = YAW_AUTOMATICALLY_WHEN_BANKED;
158                return true;
159            }
160            else if (ea.getKey()=='a')
161            {
162                _yawMode = NO_AUTOMATIC_YAW;
163                return true;
164            }
165            return false;
166
167        case(GUIEventAdapter::FRAME):
168            addMouseEvent(ea);
169            if (calcMovement()) us.requestRedraw();
170            return true;
171
172        case(GUIEventAdapter::RESIZE):
173            init(ea,us);
174            us.requestRedraw();
175            return true;
176
177        default:
178            return false;
179    }
180}
181
182void GliderManipulator::getUsage(osg::ApplicationUsage& usage) const
183{
184    usage.addKeyboardMouseBinding("Flight: Space","Reset the viewing position to home");
185    usage.addKeyboardMouseBinding("Flight: q","Automatically yaw when banked (default)");
186    usage.addKeyboardMouseBinding("Flight: a","No yaw when banked");
187}
188
189void GliderManipulator::flushMouseEventStack()
190{
191    _ga_t1 = NULL;
192    _ga_t0 = NULL;
193}
194
195
196void GliderManipulator::addMouseEvent(const GUIEventAdapter& ea)
197{
198    _ga_t1 = _ga_t0;
199    _ga_t0 = &ea;
200}
201
202
203void GliderManipulator::setByMatrix(const osg::Matrixd& matrix)
204{
205    _eye = matrix.getTrans();
206    _rotation = matrix.getRotate();
207    _distance = 1.0f;
208}
209
210osg::Matrixd GliderManipulator::getMatrix() const
211{
212    return osg::Matrixd::rotate(_rotation)*osg::Matrixd::translate(_eye);
213}
214
215osg::Matrixd GliderManipulator::getInverseMatrix() const
216{
217    return osg::Matrixd::translate(-_eye)*osg::Matrixd::rotate(_rotation.inverse());
218}
219
220void GliderManipulator::computePosition(const osg::Vec3& eye,const osg::Vec3& lv,const osg::Vec3& up)
221{
222    osg::Vec3 f(lv);
223    f.normalize();
224    osg::Vec3 s(f^up);
225    s.normalize();
226    osg::Vec3 u(s^f);
227    u.normalize();
228   
229    osg::Matrixd rotation_matrix(s[0],     u[0],     -f[0],     0.0f,
230                                s[1],     u[1],     -f[1],     0.0f,
231                                s[2],     u[2],     -f[2],     0.0f,
232                                0.0f,     0.0f,     0.0f,      1.0f);
233                   
234    _eye = eye;
235    _distance = lv.length();
236    _rotation = rotation_matrix.getRotate().inverse();
237}
238
239
240bool GliderManipulator::calcMovement()
241{
242    //_camera->setFusionDistanceMode(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE);
243
244    // return if less then two events have been added.
245    if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
246
247
248    double dt = _ga_t0->getTime()-_ga_t1->getTime();
249
250    if (dt<0.0f)
251    {
252        notify(INFO) << "warning dt = "<<dt<< std::endl;
253        dt = 0.0f;
254    }
255
256    unsigned int buttonMask = _ga_t1->getButtonMask();
257    if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
258    {
259        // pan model.
260
261        _velocity += dt*_modelScale*0.05f;
262
263    }
264    else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
265        buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
266    {
267
268        _velocity = 0.0f;
269
270    }
271    else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
272    {
273
274        _velocity -= dt*_modelScale*0.05f;
275
276    }
277
278    float dx = _ga_t0->getXnormalized();
279    float dy = _ga_t0->getYnormalized();
280   
281    // osg::notify(osg::NOTICE)<<"dx = "<<dx<<" dy = "<<dy<<"dt = "<<dt<<std::endl;
282
283    // mew - flag to reverse mouse-control mapping
284    if( getenv( "OSGHANGGLIDE_REVERSE_CONTROLS" ) )
285    {
286        dx = -dx;
287        dy = -dy;
288    }
289
290    osg::Matrixd rotation_matrix;
291    rotation_matrix.makeRotate(_rotation);
292   
293    osg::Vec3 up = osg::Vec3(0.0f,1.0f,0.0) * rotation_matrix;
294    osg::Vec3 lv = osg::Vec3(0.0f,0.0f,-1.0f) * rotation_matrix;
295
296    osg::Vec3 sv = lv^up;
297    sv.normalize();
298
299    float pitch = -inDegrees(dy*75.0f*dt);
300    float roll = inDegrees(dx*50.0f*dt);
301
302    osg::Quat delta_rotate;
303
304    osg::Quat roll_rotate;
305    osg::Quat pitch_rotate;
306
307    pitch_rotate.makeRotate(pitch,sv.x(),sv.y(),sv.z());
308    roll_rotate.makeRotate(roll,lv.x(),lv.y(),lv.z());
309
310    delta_rotate = pitch_rotate*roll_rotate;
311
312    if (_yawMode==YAW_AUTOMATICALLY_WHEN_BANKED)
313    {
314        float bank = asinf(sv.z());
315        float yaw = inRadians(bank)*dt;
316       
317        osg::Quat yaw_rotate;
318        yaw_rotate.makeRotate(yaw,0.0f,0.0f,1.0f);
319
320        delta_rotate = delta_rotate*yaw_rotate;
321    }
322
323    lv *= (_velocity*dt);
324
325    _eye += lv;
326    _rotation = _rotation*delta_rotate;
327
328    return true;
329}
Note: See TracBrowser for help on using the browser.