【轉】OSG新增自由飛行漫遊器
阿新 • • 發佈:2018-12-01
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(constosgGA::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 }