查看: 2511|回复: 4

关于相机插值漫游

[复制链接]

该用户从未签到

发表于 2011-4-11 10:10:42 | 显示全部楼层 |阅读模式
我结合pick和osganimationmakepath两个例子,想实现鼠标点击场景时,主相机的插值漫游到碰撞点处!但结果是相机一动不动。请大侠看看是怎么回事!
大致修改如下:
1在pickhandler中的pick函数加了
  1. osg::Vec3 start,end;
  2. view->getCamera()->getViewMatrixAsLookAt(position,center,up);
  3. start=position;//获取当前位置
  4. osgUtil::LineSegmentIntersector::Intersections::iterator hitr0 = intersections.begin();
  5. end=hitr0->getWorldIntersectPoint();//点击的交点即为目的地
  6. osg::ref_ptr<osg::Group>root=new osg::Group();
  7. osg::Camera* camera=new osg::Camera();
  8. camera=view->getCamera();
  9. setupAnimtkNode(camera,start,end);//调用该函数设置样条的关键帧,并在该函数中调用 AnimtkUpdateCallback
复制代码

2,在AnimtkUpdateCallback的operator()中

  1. _sampler->getValueAt(t, result);
  2. camera->setViewMatrixAsLookAt(result-osg::Vec3(0.0,1.0,0.0),result,osg::Vec3(0.0,0.0,1.0));
复制代码

全部代码:
  1. #include <osgUtil/Optimizer>
  2. #include <osgDB/ReadFile>
  3. #include <osgViewer/Viewer>
  4. #include <osgViewer/CompositeViewer>

  5. #include <osgGA/TerrainManipulator>
  6. #include <osgGA/StateSetManipulator>
  7. #include <osgGA/AnimationPathManipulator>
  8. #include <osgGA/TrackballManipulator>
  9. #include <osgGA/FlightManipulator>
  10. #include <osgGA/DriveManipulator>
  11. #include <osgGA/KeySwitchMatrixManipulator>
  12. #include <osgGA/StateSetManipulator>
  13. #include <osgGA/AnimationPathManipulator>
  14. #include <osgGA/TerrainManipulator>

  15. #include <osg/Material>
  16. #include <osg/Geode>
  17. #include <osg/BlendFunc>
  18. #include <osg/Depth>
  19. #include <osg/Projection>
  20. #include <osg/MatrixTransform>
  21. #include <osg/Camera>
  22. #include <osg/io_utils>
  23. #include <osg/ShapeDrawable>
  24. #include <osgUtil/LineSegmentIntersector>

  25. #include <osgAnimation/Sampler>
  26. #include <osgText/Text>

  27. #include <sstream>

  28. class AnimtkUpdateCallback : public osg::NodeCallback
  29. {
  30. public:
  31. META_Object(osgAnimation, AnimtkUpdateCallback);

  32. AnimtkUpdateCallback()
  33. {
  34. _sampler = new osgAnimation::Vec3CubicBezierSampler;
  35. _playing = false;
  36. _lastUpdate = 0;
  37. }
  38. AnimtkUpdateCallback(const AnimtkUpdateCallback& val, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY):
  39. osg::Object(val, copyop),
  40. osg::NodeCallback(val, copyop),
  41. _sampler(val._sampler),
  42. _startTime(val._startTime),
  43. _currentTime(val._currentTime),
  44. _playing(val._playing),
  45. _lastUpdate(val._lastUpdate)
  46. {
  47. }

  48. /** Callback method called by the NodeVisitor when visiting a node.*/
  49. virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
  50. {
  51. if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR &&
  52. nv->getFrameStamp() &&
  53. nv->getFrameStamp()->getFrameNumber() != _lastUpdate)
  54. {

  55. _lastUpdate = nv->getFrameStamp()->getFrameNumber();
  56. _currentTime = osg::Timer::instance()->tick();

  57. if (_playing && _sampler.get() && _sampler->getKeyframeContainer())
  58. {
  59. //osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);
  60. osg::Camera* camera = dynamic_cast<osg::Camera*>(node);
  61. if (camera) {
  62. osg::Vec3 result;
  63. float t = osg::Timer::instance()->delta_s(_startTime, _currentTime);
  64. float duration = _sampler->getEndTime() - _sampler->getStartTime();
  65. //t = fmod(t, duration);
  66. t += _sampler->getStartTime();
  67. _sampler->getValueAt(t, result);
  68. //transform->setMatrix(osg::Matrix::translate(result));
  69. camera->setViewMatrixAsLookAt(result-osg::Vec3(0.0,1.0,0.0),result,osg::Vec3(0.0,0.0,1.0));
  70. }

  71. }
  72. }
  73. // note, callback is responsible for scenegraph traversal so
  74. // they must call traverse(node,nv) to ensure that the
  75. // scene graph subtree (and associated callbacks) are traversed.
  76. traverse(node,nv);
  77. }

  78. void start() { _startTime = osg::Timer::instance()->tick(); _currentTime = _startTime; _playing = true;}
  79. void stop() { _currentTime = _startTime; _playing = false;}

  80. osg::ref_ptr<osgAnimation::Vec3CubicBezierSampler> _sampler;
  81. osg::Timer_t _startTime;
  82. osg::Timer_t _currentTime;
  83. bool _playing;
  84. int _lastUpdate;
  85. };
  86. osg::MatrixTransform* setupAnimtkNode(osg::Camera* camera,osg::Vec3 start,osg::Vec3 end)
  87. {
  88. osg::Vec3 v[2];

  89. osg::Vec3 startToend=end-start;
  90. /*startToend.x()*=0.5;
  91. startToend.y()*=0.5;
  92. startToend.z()*=0.5;*/
  93. v[0] = start;
  94. v[1] = v[0]+startToend;
  95. /*v[2] = v[1]+startToend;
  96. v[3] = v[2]+startToend;
  97. v[4] = v[3]+startToend;
  98. v[5] = v[4]+startToend;*/

  99. osg::MatrixTransform* node = new osg::MatrixTransform();
  100. //AnimtkUpdateCallback* callback = new MakePathDistanceCallback(staticGeode);
  101. AnimtkUpdateCallback* callback = new AnimtkUpdateCallback();
  102. osgAnimation::Vec3CubicBezierKeyframeContainer* keys = callback->_sampler->getOrCreateKeyframeContainer();

  103. keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(0, osgAnimation::Vec3CubicBezier(
  104. v[0],
  105. v[0] + (v[0] - v[1]),
  106. v[1] - (v[1] - v[0])
  107. )));

  108. keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(6, osgAnimation::Vec3CubicBezier(
  109. v[1],
  110. v[1] + (v[1] - v[0]),
  111. v[0] - (v[0] - v[1])
  112. )));

  113. /*keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(4, osgAnimation::Vec3CubicBezier(
  114. v[2],
  115. v[2] + (v[2] - v[1]),
  116. v[0] - (v[0] - v[2])
  117. )));

  118. keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(6, osgAnimation::Vec3CubicBezier(
  119. v[3],
  120. v[3] + (v[3] - v[2]),
  121. v[4] - (v[4] - v[3])
  122. )));

  123. keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(8, osgAnimation::Vec3CubicBezier(
  124. v[4],
  125. v[4] + (v[4] - v[3]),
  126. v[5] - (v[5] - v[4])
  127. )));
  128. keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(12, osgAnimation::Vec3CubicBezier(
  129. v[5],
  130. v[5] + (v[5] - v[4]),
  131. v[0] - (v[0] - v[5])
  132. )));*/

  133. callback->start();
  134. camera->setUpdateCallback(callback);

  135. //osg::Geode* geode = new osg::Geode();

  136. //geode->setStateSet(setupStateSet());
  137. //geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 2)));

  138. //node->addChild(geode);

  139. return node;
  140. }
  141. //////////////////////////////////////////////////////////////////////////

  142. // class to handle events with a pick
  143. class PickHandler : public osgGA::GUIEventHandler {
  144. public:

  145. PickHandler(osgText::Text* updateText):
  146. _updateText(updateText) {}

  147. ~PickHandler() {}

  148. bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);

  149. virtual void pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea);

  150. void setLabel(const std::string& name)
  151. {
  152. if (_updateText.get()) _updateText->setText(name);
  153. }

  154. protected:

  155. //得到当前视图矩阵
  156. osg::Vec3 position;
  157. osg::Vec3 center;
  158. osg::Vec3 up;
  159. osg::ref_ptr<osgText::Text> _updateText;
  160. };

  161. bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
  162. {
  163. switch(ea.getEventType())
  164. {
  165. /* case(osgGA::GUIEventAdapter::FRAME):
  166. {
  167. osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
  168. if (view) view->getCamera()->getViewMatrixAsLookAt(position,center,up);
  169. osg::Vec3 delta = center-position;
  170. position = position + delta/2.0;
  171. view->getCamera()->setViewMatrixAsLookAt(position, center, up);
  172. return false;
  173. }*/
  174. case(osgGA::GUIEventAdapter::PUSH):
  175. {
  176. osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
  177. if (view) pick(view,ea);
  178. return false;
  179. }
  180. case(osgGA::GUIEventAdapter::KEYDOWN):
  181. {
  182. if (ea.getKey()=='c')
  183. {
  184. osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
  185. osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter(ea);
  186. event->setX((ea.getXmin()+ea.getXmax())*0.5);
  187. event->setY((ea.getYmin()+ea.getYmax())*0.5);
  188. view->requestWarpPointer((ea.getXmin()+ea.getXmax())/2.0f,(ea.getYmin()+ea.getYmax())/2.0f);
  189. if (view) pick(view,*event);
  190. }
  191. return false;
  192. }
  193. default:
  194. return false;
  195. }
  196. }

  197. void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea)
  198. {
  199. osgUtil::LineSegmentIntersector::Intersections intersections;

  200. std::string gdlist="";
  201. float x = ea.getX();
  202. float y = ea.getY();
  203. #if 0
  204. osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y);
  205. osgUtil::IntersectionVisitor iv(picker.get());
  206. view->getCamera()->accept(iv);
  207. if (picker->containsIntersections())
  208. {
  209. intersections = picker->getIntersections();
  210. #else
  211. if (view->computeIntersections(x,y,intersections))
  212. {
  213. #endif
  214. //////////////////////////////////////////////////////////////////////////

  215. osg::Vec3 start,end;
  216. view->getCamera()->getViewMatrixAsLookAt(position,center,up);
  217. start=position;
  218. osgUtil::LineSegmentIntersector::Intersections::iterator hitr0 = intersections.begin();
  219. end=hitr0->getWorldIntersectPoint();
  220. osg::ref_ptr<osg::Group>root=new osg::Group();
  221. osg::Camera* camera=new osg::Camera();
  222. camera=view->getCamera();
  223. setupAnimtkNode(camera,start,end);
  224. /*osg::Geode* geode = new osg::Geode();
  225. root=view->getSceneData()->asGroup();
  226. root->addChild(setupAnimtkNode(geode,start,end));
  227. root->addChild(geode);*/
  228. //////////////////////////////////////////////////////////////////////////

  229. for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
  230. hitr != intersections.end();
  231. ++hitr)
  232. {
  233. std::ostringstream os;
  234. if (!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty()))
  235. {
  236. // the geodes are identified by name.
  237. os<<"Object ""<<hitr->nodePath.back()->getName()<<"""<<std::endl;
  238. }
  239. else if (hitr->drawable.valid())
  240. {
  241. os<<"Object ""<<hitr->drawable->className()<<"""<<std::endl;
  242. }

  243. os<<" local coords vertex("<< hitr->getLocalIntersectPoint()<<")"<<" normal("<<hitr->getLocalIntersectNormal()<<")"<<std::endl;
  244. os<<" world coords vertex("<< hitr->getWorldIntersectPoint()<<")"<<" normal("<<hitr->getWorldIntersectNormal()<<")"<<std::endl;

  245. const osgUtil::LineSegmentIntersector::Intersection::IndexList& vil = hitr->indexList;
  246. for(unsigned int i=0;i<vil.size();++i)
  247. {
  248. os<<" vertex indices ["<<i<<"] = "<<vil[i]<<std::endl;
  249. }

  250. gdlist += os.str();
  251. }
  252. }
  253. setLabel(gdlist);
  254. }

  255. osg::Node* createHUD(osgText::Text* updateText)
  256. {
  257. osg::Camera* hudCamera = new osg::Camera;
  258. hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
  259. hudCamera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
  260. hudCamera->setViewMatrix(osg::Matrix::identity());
  261. hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
  262. hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);

  263. std::string timesFont("fonts/times.ttf");

  264. // turn lighting off for the text and disable depth test to ensure its always ontop.
  265. osg::Vec3 position(150.0f,800.0f,0.0f);
  266. osg::Vec3 delta(0.0f,-60.0f,0.0f);

  267. {
  268. osg::Geode* geode = new osg::Geode();
  269. osg::StateSet* stateset = geode->getOrCreateStateSet();
  270. stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
  271. stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
  272. geode->setName("simple");
  273. hudCamera->addChild(geode);

  274. osgText::Text* text = new osgText::Text;
  275. geode->addDrawable( text );

  276. text->setFont(timesFont);
  277. text->setText("Picking in Head Up Displays is simple!");
  278. text->setPosition(position);

  279. position += delta;
  280. }

  281. for (int i=0; i<=5; i++) {
  282. osg::Vec3 dy(0.0f,-30.0f,0.0f);
  283. osg::Vec3 dx(120.0f,0.0f,0.0f);
  284. osg::Geode* geode = new osg::Geode();
  285. osg::StateSet* stateset = geode->getOrCreateStateSet();
  286. const char *opts[]={"One", "Two", "Three", "January", "Feb", "2003"};
  287. osg::Geometry *quad=new osg::Geometry;
  288. stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
  289. stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
  290. std::string name="subOption";
  291. name += " ";
  292. name += std::string(opts[i]);
  293. geode->setName(name);
  294. osg::Vec3Array* vertices = new osg::Vec3Array(4); // 1 quad
  295. osg::Vec4Array* colors = new osg::Vec4Array;
  296. colors = new osg::Vec4Array;
  297. colors->push_back(osg::Vec4(0.8-0.1*i,0.1*i,0.2*i, 1.0));
  298. quad->setColorArray(colors);
  299. quad->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
  300. (*vertices)[0]=position;
  301. (*vertices)[1]=position+dx;
  302. (*vertices)[2]=position+dx+dy;
  303. (*vertices)[3]=position+dy;
  304. quad->setVertexArray(vertices);
  305. quad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
  306. geode->addDrawable(quad);
  307. hudCamera->addChild(geode);

  308. position += delta;
  309. }



  310. { // this displays what has been selected
  311. osg::Geode* geode = new osg::Geode();
  312. osg::StateSet* stateset = geode->getOrCreateStateSet();
  313. stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
  314. stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
  315. geode->setName("The text label");
  316. geode->addDrawable( updateText );
  317. hudCamera->addChild(geode);

  318. updateText->setCharacterSize(20.0f);
  319. updateText->setFont(timesFont);
  320. updateText->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
  321. updateText->setText("");
  322. updateText->setPosition(position);
  323. updateText->setDataVariance(osg::Object::DYNAMIC);

  324. position += delta;
  325. }

  326. return hudCamera;

  327. }

  328. int main( int argc, char **argv )
  329. {
  330. // use an ArgumentParser object to manage the program arguments.
  331. osg::ArgumentParser arguments(&argc,argv);

  332. // read the scene from the list of file specified commandline args.
  333. osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

  334. if (!scene && arguments.read("--relative-camera-scene"))
  335. {
  336. // Create a test scene with a camera that has a relative reference frame.
  337. osg::Group* group = new osg::Group();

  338. osg::Geode* sphere = new osg::Geode();
  339. sphere->setName("Sphere");
  340. sphere->addDrawable(new osg::ShapeDrawable(new osg::Sphere()));

  341. osg::Geode* cube = new osg::Geode();
  342. cube->setName("Cube");
  343. cube->addDrawable(new osg::ShapeDrawable(new osg::Box()));

  344. osg::Camera* camera = new osg::Camera();
  345. camera->setRenderOrder(osg::Camera::POST_RENDER);
  346. camera->setClearMask(GL_DEPTH_BUFFER_BIT);
  347. camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
  348. camera->setViewMatrix(osg::Matrix::translate(-2, 0, 0));

  349. osg::MatrixTransform* xform = new osg::MatrixTransform(osg::Matrix::translate(1, 1, 1));
  350. xform->addChild(camera);

  351. group->addChild(sphere);
  352. group->addChild(xform);
  353. camera->addChild(cube);

  354. scene = group;
  355. }

  356. // if not loaded assume no arguments passed in, try use default mode instead.
  357. if (!scene) scene = osgDB::readNodeFile("lz.osg");

  358. osg::ref_ptr<osg::Group> group = dynamic_cast<osg::Group*>(scene.get());
  359. if (!group)
  360. {
  361. group = new osg::Group;
  362. group->addChild(scene.get());
  363. }

  364. osg::ref_ptr<osgText::Text> updateText = new osgText::Text;

  365. // add the HUD subgraph.
  366. group->addChild(createHUD(updateText.get()));

  367. if (arguments.read("--CompositeViewer"))
  368. {
  369. osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
  370. // add the handler for doing the picking
  371. view->addEventHandler(new PickHandler(updateText.get()));

  372. // set the scene to render
  373. view->setSceneData(group.get());

  374. view->setUpViewAcrossAllScreens();

  375. osgViewer::CompositeViewer viewer;
  376. viewer.addView(view.get());

  377. return viewer.run();

  378. }
  379. else
  380. {
  381. osgViewer::Viewer viewer;


  382. // add all the camera manipulators
  383. {
  384. osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

  385. keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
  386. keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
  387. keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );

  388. unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
  389. keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

  390. std::string pathfile;
  391. char keyForAnimationPath = '5';
  392. while (arguments.read("-p",pathfile))
  393. {
  394. osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
  395. if (apm || !apm->valid())
  396. {
  397. num = keyswitchManipulator->getNumMatrixManipulators();
  398. keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
  399. ++keyForAnimationPath;
  400. }
  401. }
  402. keyswitchManipulator->selectMatrixManipulator(num);

  403. viewer.setCameraManipulator( keyswitchManipulator.get() );
  404. }

  405. // add the handler for doing the picking
  406. viewer.addEventHandler(new PickHandler(updateText.get()));

  407. // set the scene to render
  408. viewer.setSceneData(group.get());

  409. return viewer.run();
  410. }

  411. }
复制代码

该用户从未签到

发表于 2011-4-11 16:58:06 | 显示全部楼层
您可以首先测试这段程序在直接指定一个路径终点的情况下能否运行,然后检查您的鼠标点击是否得到了一个正确可用的终点——这样您可以非常快地定位自己的问题

该用户从未签到

 楼主| 发表于 2011-4-11 18:32:48 | 显示全部楼层
回复 2# array


    我测试过点击之后,从起点处发射一个球到终点,是成功的!但换成相机就不行了,感觉就是
camera->setViewMatrixAsLookAt(result-osg::Vec3(0.0,1.0,0.0),result,osg::Vec3(0.0,0.0,1.0));没有执行

该用户从未签到

发表于 2011-4-12 08:42:26 | 显示全部楼层
是否是受到了场景漫游器的影响?可以设置getCameraManipulator()->setByInverseMatrix()来替代camera的设置

该用户从未签到

 楼主| 发表于 2011-4-12 10:43:38 | 显示全部楼层
恩,这个可以用!看来漫游器是会影响camera的设置!谢谢array!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表