【转】OSG添加自由飞行漫游器

 1 //头文件里
 2 #define MANIPULATOR_W 0x01
 3 #define MANIPULATOR_A 0x02
 4 #define MANIPULATOR_S 0x04
 5 #define MANIPULATOR_D 0x08
 6 #define MANIPULATOR_R 0x10
 7 #define MANIPULATOR_F 0x20
 8 
 9 #define MANIPULATOR_MAX 127
10 //所有漫游器都必须实现的4个纯虚函数  
11         virtual void setByMatrix(const osg::Matrixd& matrix);  //设置相机的位置姿态矩阵  
12         virtual void setByInverseMatrix(const osg::Matrixd& matrix) {}  //设置相机的视图矩阵  
13         virtual osg::Matrixd getMatrix() const;  //获取相机的姿态矩阵 
14         virtual osg::Matrixd getInverseMatrix() const;   //获取相机的视图矩阵 
15 
16         //所有操作在这里响应
17         virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
18 
19 
20         void reFreshSawEarth();//在当前经纬度,姿态回正:1.视点向地面 2.头部向正北
21         void reFreshSawSkyline(osg::Vec3d eye=osg::Vec3d(0,0,0));//在当前经纬度,头部回正:1.视点中心不变 2.头部向天
22 
23         osg::Vec3d   _eye;               //视点位置  
24         osg::Quat    _rotate;            //旋转姿态 
25         osg::Quat    _rotateNew;            //旋转姿态 
26         osg::ref_ptr<osg::Node>  _root;
27 
28         osg::observer_ptr<osg::Node> _node;
29         osg::observer_ptr<osgEarth::MapNode>   _mapNode;
30 
31         osg::ref_ptr<const osgEarth::SpatialReference> _srs;
32 
33         float        _speed;                //速度
34         float        _speedBase;
35         float       _speedMultiple;        //速度倍数
36         float        _timerRoll;
37         bool        _updateAltitude;
38         bool        _updateRollStart;        //更新滚转
39         bool        _updateRoll;        //更新滚转
40         bool        _openStree;            
41         // Internal event stack comprising last two mouse events.
42         osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t1;
43         osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0;
  1 //cpp文件
  2 void setByMatrix(const osg::Matrixd& matrix)//设置相机的位置姿态矩阵  
  3 {
  4     gMinpulatorContgrol = 0;
  5     _eye = matrix.getTrans();
  6     osg::Vec3d  v3Eye, v3Center, v3Up;
  7     v3Eye = _eye;//使用相机实际位置
  8     osg::Vec3d v3EyeLonLat;
  9     _srs->transformFromWorld(v3Eye, v3EyeLonLat);
 10     //先获取当前位置的经纬度,再获取当前正上,正北
 11     osg::Matrix mRealAttitude;
 12 
 13     if (v3EyeLonLat.z() < 10000)//距离地面1千万米以内需要矫正
 14         //reFreshSawSkyline();
 15         _updateRoll = true;
 16     else
 17         reFreshSawEarth();
 18 }  
 19 
 20 osg::Matrixd getInverseMatrix() const
 21 {
 22     osg::Matrix mat;
 23     mat.setRotate(-_rotate);
 24     mat.preMultTranslate(-_eye);
 25     return mat;
 26     //return osg::Matrixd::inverse(getMatrix());
 27 }void setNode(osg::Node* node)
 28 {
 29     // you can only set the node if it has not already been set, OR if you are setting
 30     // it to NULL. (So to change it, you must first set it to NULL.) This is to prevent
 31     // OSG from overwriting the node after you have already set on manually.
 32     if (node == 0L || !_node.valid())
 33     {
 34         _root = node;
 35         _node = node;
 36         _mapNode = 0L;
 37         _srs = 0L;
 38 
 39         established();
 40 
 41         osg::Matrix matrixGood1;
 42         GeoPoint point1(_srs, 0, 0, 10000.0);
 43         point1.createLocalToWorld(matrixGood1);
 44 
 45         _eye = matrixGood1.getTrans();
 46 
 47         osg::Vec3d worldup;
 48         point1.createWorldUpVector(worldup);
 49 
 50         osg::Matrix mat;
 51         matrixGood1.getRotate().get(mat);
 52         osg::Vec3d eye, center, up;
 53         mat.getLookAt(eye, center, up);
 54         mat.makeLookAt(eye, -worldup, up);
 55 
 56         _rotate = mat.getRotate();
 57 
 58     }
 59 }
 60 void reFreshSawSkyline(osg::Vec3d eye)
 61 {
 62     osg::Vec3d v3Eye;
 63     osg::Vec3d v3EyeLonLat;
 64     v3Eye = _eye;//使用相机实际位置
 65     
 66     if (eye != osg::Vec3d(0, 0, 0))
 67     {
 68         v3Eye += eye;
 69     }
 70 
 71     _srs->transformFromWorld(v3Eye, v3EyeLonLat);
 72     //先获取当前位置的经纬度,再获取当前正上,正北
 73 
 74     if (v3EyeLonLat.z() < 10000)//距离地面1千万米以内需要矫正
 75     {
 76             osg::Matrix mRealAttitude;
 77             GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
 78             gEyeGeo.createLocalToWorld(mRealAttitude);
 79 
 80             osg::Vec3d v3HorizonUp;//指天向量
 81             gEyeGeo.createWorldUpVector(v3HorizonUp);
 82 
 83             _rotate.get(mRealAttitude);//要使用当前相机的姿态
 84             osg::Vec3d  theEye,v3Center, v3Up;
 85             mRealAttitude.getLookAt(theEye, v3Center, v3Up);//获取新的位置和姿态
 86             osg::Vec3d v3Direction = v3Center - theEye;
 87             mRealAttitude.makeLookAt(osg::Vec3d(0, 0, 0), v3Direction, v3HorizonUp);
 88             _rotate = mRealAttitude.getRotate();
 89     
 90     }
 91     
 92     //_eye = v3Eye;
 93 }
 94 
 95 void  reFreshSawEarth()
 96 {
 97     osg::Vec3d  v3Eye, v3Center, v3Up;
 98     v3Eye = _eye;//使用相机实际位置
 99     osg::Vec3d v3EyeLonLat;
100     _srs->transformFromWorld(v3Eye, v3EyeLonLat);
101         //先获取当前位置的经纬度,再获取当前正上,正北
102         osg::Matrix mRealAttitude;
103 
104     if (v3EyeLonLat.z() < 0)//v3EyeLonLat.z()是眼点实际海拔
105         v3EyeLonLat.z() = 100;//将海拔0以下的物体拉到海拔100米
106 
107     GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
108     gEyeGeo.createLocalToWorld(mRealAttitude);
109 
110     osg::Vec3d v3HorizonUp;//指天向量
111     gEyeGeo.createWorldUpVector(v3HorizonUp);
112 
113     _eye = mRealAttitude.getTrans();
114 
115     mRealAttitude.getLookAt(v3Eye, v3Center, v3Up);//获取新的位置和姿态
116 
117     osg::Matrix mDeviationAttitude;//向北位置偏移0.00001纬度,为了计算正北方向
118     GeoPoint gDeviationEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y() + 0.00001, v3EyeLonLat.z());
119     gDeviationEyeGeo.createLocalToWorld(mDeviationAttitude);
120     osg::Vec3d v3DeviationNorthPoint = mDeviationAttitude.getTrans();
121     osg::Vec3d v3NorthHeadUp = v3DeviationNorthPoint - v3Eye;
122     v3NorthHeadUp.normalize();//指北向量
123 
124     if (v3EyeLonLat.y() < 89.99999  && v3EyeLonLat.y() > -90.0)
125     {
126         mRealAttitude.makeLookAt(osg::Vec3d(0, 0, 0), -v3HorizonUp, v3NorthHeadUp);
127     }
128     _rotate = mRealAttitude.getRotate();
129 }
130 
131 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
132 {
133     bool handled = false;
134 
135     switch (ea.getEventType())
136     {
137     case(osgGA::GUIEventAdapter::FRAME):
138     {
139         if (gMinpulatorContgrol & MANIPULATOR_MAX)
140         {
141             osg::Vec3d   v3Direction;         //视点方向  
142             osg::Matrix mCameraQuat;
143             osg::Vec3d  v3Eye, v3Center, v3Up;
144             _rotate.get(mCameraQuat);
145             mCameraQuat.getLookAt(v3Eye, v3Center, v3Up);//这里的v3Eye不是实际相机的位置,而是0,0,0
146             v3Direction = v3Center - v3Eye;
147             v3Direction.normalize();
148             /*********************************************************/
149             osg::Vec3d RealEye = _eye;
150             osg::Vec3d testHight = v3Direction*100;
151             double _DvalueHight = 0.0;
152             {
153                 osg::Vec3d testLonLat1, testLonLat2;
154                 _srs->transformFromWorld(RealEye, testLonLat1);
155                 RealEye = _eye;
156                 osg::Vec3d testEye = RealEye + testHight;
157                 _srs->transformFromWorld(testEye, testLonLat2);
158                 _DvalueHight = abs(testLonLat2.z() - testLonLat1.z());
159 
160                 if (_DvalueHight < 10)//趋近水平使用水平方向
161                 {
162                     testLonLat2.z() = testLonLat1.z();
163                     _srs->transformToWorld(testLonLat2, testEye);
164                     v3Direction = testEye - RealEye;
165                     v3Direction.normalize();
166                 }
167             }
168 
169             osg::Vec3d v3CrossVector = v3Up^v3Direction;
170             v3CrossVector.normalize();
171 
172             /*********************************************************/
173             //计算地面高度
174             osg::Vec3d v3EyeLonLat;
175             v3Eye = _eye;
176             _srs->transformFromWorld(v3Eye, v3EyeLonLat);
177             double mAltitude = VRE_ENGINE.GetToolsFunc()->GetGeoPointAltitude(v3EyeLonLat.x(), v3EyeLonLat.y());
178             float height = osg::clampBetween(v3EyeLonLat.z() - mAltitude, 100.0, 1000000.0);
179             _speed = height / 200.0;//根据离地面高度计算当前速度值
180             RealEye = _eye;
181             if (gMinpulatorContgrol & MANIPULATOR_W)
182             {
183                 RealEye += v3Direction * _speed *_speedMultiple * _speedBase;
184                 _updateAltitude = false;
185             }if (gMinpulatorContgrol & MANIPULATOR_A)
186             {
187                 RealEye += v3CrossVector * _speed *_speedMultiple * _speedBase;
188                 _updateAltitude = false;
189             }if (gMinpulatorContgrol & MANIPULATOR_S)
190             {
191                 RealEye -= v3Direction * _speed *_speedMultiple * _speedBase;
192                 _updateAltitude = false;
193             }if (gMinpulatorContgrol & MANIPULATOR_D)
194             {
195                 RealEye -= v3CrossVector * _speed *_speedMultiple * _speedBase;
196                 _updateAltitude = false;
197             }if (gMinpulatorContgrol & MANIPULATOR_R)
198             {
199                 //_eye += v3Up * _speed *_speedMultiple * _speedBase;
200                 v3EyeLonLat.z() += _speed *_speedMultiple * _speedBase;
201                 osg::Vec3d newv3Eye;
202                 _srs->transformToWorld(v3EyeLonLat, newv3Eye);
203                 RealEye = newv3Eye;
204                 _updateAltitude = false;
205             }if (gMinpulatorContgrol & MANIPULATOR_F)
206             {
207                 //_eye -= v3Up * _speed *_speedMultiple * _speedBase;
208                 v3EyeLonLat.z() -= _speed *_speedMultiple * _speedBase;
209                 osg::Vec3d newv3Eye;
210                 _srs->transformToWorld(v3EyeLonLat, newv3Eye);
211                 RealEye = newv3Eye;
212                 _updateAltitude = false;
213             }
214 
215             _eye = RealEye;
216             //reFreshSawSkyline(RealEye);
217         }
218     
219         if (_updateRoll)
220         {
221             osg::Vec3d v3Eye;
222             osg::Vec3d v3EyeLonLat;
223             v3Eye = _eye;//使用相机实际位置
224             _srs->transformFromWorld(v3Eye, v3EyeLonLat);
225             //先获取当前位置的经纬度,再获取当前正上,正北
226 
227             if (v3EyeLonLat.z() < 10000)//距离地面1千万米以内需要矫正
228             {
229                 osg::Matrix mRealAttitude;
230                 GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
231                 gEyeGeo.createLocalToWorld(mRealAttitude);
232 
233                 osg::Vec3d v3HorizonUp;//指天向量
234                 gEyeGeo.createWorldUpVector(v3HorizonUp);
235 
236                 _rotate.get(mRealAttitude);//要使用当前相机的姿态
237                 osg::Vec3d  theEye, v3Center, v3Up;
238                 mRealAttitude.getLookAt(theEye, v3Center, v3Up);//获取新的位置和姿态
239                 osg::Vec3d v3Direction = v3Center - theEye;
240                 mRealAttitude.makeLookAt(osg::Vec3d(0, 0, 0), v3Direction, v3HorizonUp);
241                 _rotateNew = mRealAttitude.getRotate();
242                 _updateRoll = false;
243                 _updateRollStart = true;
244                 _timerRoll = 0.0;
245             }
246             else
247             {
248                 _updateRoll = false;
249             }
250         }
251 
252         if (_updateRollStart)
253         {
254             _timerRoll += 0.01;
255             if (_timerRoll > 1.0)
256             {
257                 _timerRoll = 1.0;
258                 _updateRollStart = false;
259             }
260             _rotate.slerp(_timerRoll, _rotate, _rotateNew);
261         }
262 
263         if (_updateAltitude)
264         {
265             //每帧调节高度
266             osg::Vec3d newEye = _eye;
267             osg::Vec3d v3EyeLonLat;
268             _srs->transformFromWorld(newEye, v3EyeLonLat);
269             double _mAltitude = v3EyeLonLat.z();
270             double mAltitude = VRE_ENGINE.GetToolsFunc()->GetGeoPointAltitude(v3EyeLonLat.x(), v3EyeLonLat.y()) + MANIPULATOR_PERSONVIEWHEIGHT;
271             double interprolationAltitude = mAltitude - _mAltitude;
272             if (interprolationAltitude > 1)
273             {
274                 interprolationAltitude /= 10.0;
275                 v3EyeLonLat.z() += interprolationAltitude;
276             }
277             else if (interprolationAltitude > 0.1)
278             {
279                 v3EyeLonLat.z() += 0.1;
280             }
281             else
282             {
283                 _updateAltitude = false;
284             }
285             osg::Vec3d FinalEye;
286             _srs->transformToWorld(v3EyeLonLat, FinalEye);
287             _eye = FinalEye;
288         }
289     }break;
290     case(osgGA::GUIEventAdapter::PUSH):
291     {
292     }break;
293     case(osgGA::GUIEventAdapter::RELEASE):
294     {
295         flushMouseEventStack();
296     }break;
297     case(osgGA::GUIEventAdapter::DRAG):
298     {
299         if (calcMovement(ea))//根据鼠标在屏幕中的位置调整相机转向
300         {
301             //reFreshSawSkyline();
302             _updateRoll = true;
303             us.requestRedraw();
304             return true;
305         }
306     };
307     case(osgGA::GUIEventAdapter::SCROLL)://由于已经每帧都调整姿态,所以手动滚动不需要了
308     {
309         osg::Vec3d   v3Direction;         //视点方向  
310         osg::Matrix mCameraQuat;
311         osg::Vec3d  v3Eye, v3Center, v3Up;
312         _rotate.get(mCameraQuat);
313         mCameraQuat.getLookAt(v3Eye, v3Center, v3Up);//这里的v3Eye不是实际相机的位置,而是0,0,0
314         v3Direction = v3Center - v3Eye;
315         v3Direction.normalize();
316         osg::Vec3d v3CrossVector = v3Up^v3Direction;
317         v3CrossVector.normalize();
318         switch (ea.getScrollingMotion())
319         {
320         case osgGA::GUIEventAdapter::ScrollingMotion::SCROLL_UP:
321         {
322             _eye += v3Direction * _speed *_speedMultiple;
323             //reFreshSawSkyline();
324             _updateRoll = true;
325         }break;
326         case osgGA::GUIEventAdapter::ScrollingMotion::SCROLL_DOWN:
327         {
328             _eye -= v3Direction * _speed *_speedMultiple;
329             //reFreshSawSkyline();
330             _updateRoll = true;
331         }break;
332         }
333         //reFreshSawSkyline();
334 
335         return true;
336     }break;
337     case (osgGA::GUIEventAdapter::KEYDOWN):
338     {
339         if (ea.getKey() == 'r' || ea.getKey() == 'R')//往头部前进
340         {
341             gMinpulatorContgrol |= MANIPULATOR_R;
342         }
343         if (ea.getKey() == 'f' || ea.getKey() == 'F')//往尾部后退
344         {
345             gMinpulatorContgrol |= MANIPULATOR_F;
346         }
347         if (ea.getKey() == 'w' || ea.getKey() == 'W' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)//前进
348         {
349             gMinpulatorContgrol |= MANIPULATOR_W;
350         }
351         if (ea.getKey() == 's' || ea.getKey() == 'S' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)//后退
352         {
353             gMinpulatorContgrol |= MANIPULATOR_S;
354         }
355         if (ea.getKey() == 'a' || ea.getKey() == 'A' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)//左移
356         {
357             gMinpulatorContgrol |= MANIPULATOR_A;
358         }
359         if (ea.getKey() == 'd' || ea.getKey() == 'D' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)//右移
360         {
361             gMinpulatorContgrol |= MANIPULATOR_D;
362         }
363         if (ea.getKey() == '-' || ea.getKey() == '_' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)//减10倍移动速度
364         {
365             _speedBase /= 10.0;
366             if (_speedBase < 0.1)
367             {
368                 _speedBase = 0.1;
369             }
370         }
371         if (ea.getKey() == '=' || ea.getKey() == '+' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)//加10倍移动速度
372         {
373             _speedBase *= 10.0;
374             if (_speedBase > 1000.0)
375             {
376                 _speedBase = 1000.0;
377             }
378         }
379 
380         if (ea.getKey() == 'h' || ea.getKey() == 'H')//在当前经纬度,姿态回正:1.视点向地面 2.头部向正北
381         {
382             reFreshSawEarth();
383         }
384         if (ea.getKey() == 'g' || ea.getKey() == 'G')//在当前经纬度,头部回正:1.视点中心不变 2.头部向天
385         {
386             reFreshSawSkyline();
387         }
388         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L || ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_R)
389         {
390             _speedMultiple = 10.0;
391         }
392     }break;
393     case (osgGA::GUIEventAdapter::KEYUP):
394     {
395         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L || ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_R)
396         {
397             _speedMultiple = 1.0;
398         }
399         if (ea.getKey() == 'a' || ea.getKey() == 'A' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)//左移
400         {
401             gMinpulatorContgrol &= ~MANIPULATOR_A;
402             _updateAltitude = true;
403         }
404         if (ea.getKey() == 'd' || ea.getKey() == 'D' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)//右移
405         {
406             gMinpulatorContgrol &= ~MANIPULATOR_D;
407             _updateAltitude = true;
408         }
409         if (ea.getKey() == 'w' || ea.getKey() == 'W' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)//前进
410         {
411             gMinpulatorContgrol &= ~MANIPULATOR_W;
412             _updateAltitude = true;
413         }
414         if (ea.getKey() == 'q' || ea.getKey() == 'Q' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)//往头部前进
415         {
416             gMinpulatorContgrol &= ~MANIPULATOR_R;
417             _updateAltitude = true;
418         }
419         if (ea.getKey() == 'e' || ea.getKey() == 'E' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)//往尾部后退
420         {
421             gMinpulatorContgrol &= ~MANIPULATOR_F;
422             _updateAltitude = true;
423         }
424         if (ea.getKey() == 's' || ea.getKey() == 'S' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)//后退
425         {
426             gMinpulatorContgrol &= ~MANIPULATOR_S;
427             _updateAltitude = true;
428         }
429     }break;
430     default:
431         break;
432     }
433 
434     return handled;
435 }

猜你喜欢

转载自www.cnblogs.com/tianshanhangui/p/10051610.html