码迷,mamicode.com
首页 > 其他好文 > 详细

OSG实现场景漫游(转载)

时间:2016-08-17 23:04:49      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:

OSG实现场景漫游

下面的代码将可以实现场景模型的导入,然后在里面任意行走,于此同时还实现了碰撞检测。

 

源代码下载地址:

 

技术分享

 

技术分享

 1 /*
 2  * File        : Travel.cpp
 3  * Description : 
 4  * Author      : GuoShaoHao
 5  * E-mail      : gsh0913@qq.com
 6  * Date        : 2011/01/08
 7  * 
 8  * CopyRight @ South China Institute of Software Engineering,.GZU
 9  *
10  */
11 
12 #include <iostream>
13 #include <osgViewer/Viewer>
14 #include <osg/Node>
15 #include <osg/Geode>
16 #include <osg/Group>
17 
18 #include <osgDB/ReadFile>
19 #include <osgDB/WriteFile>
20 
21 #include <osgUtil/Optimizer>
22 
23 #include <osg/MatrixTransform>
24 #include <osgViewer/ViewerEventHandlers>
25 #include <osgGA/StateSetManipulator>
26 
27 #include "TravelManipulator.h"
28 
29 using namespace std;
30 
31 
32 int main()
33 {
34     //创建Viewer对象
35     osg::ref_ptr<osgViewer::Viewer>viewer = new osgViewer::Viewer();
36 
37     //添加状态事件
38     //viewer.get()->addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
39     //窗口大小变化事件
40     viewer.get()->addEventHandler(new osgViewer::WindowSizeHandler);
41     //添加一些常用状态设置
42     viewer.get()->addEventHandler(new osgViewer::StatsHandler);
43 
44     // 把漫游器加入到场景中
45     TravelManipulator::TravelToScence(viewer.get());
46 
47     osg::ref_ptr<osg::Group>root = new osg::Group();
48 
49     // 读取地形
50     osg::ref_ptr<osg::Node>node = osgDB::readNodeFile("D://OSG//data//lz.osg");
51 
52     // 读取飞机
53     //osg::ref_ptr<osg::Node>tank = osgDB::readNodeFile("F://Models//Amx30//Amx30.IVE");
54     osg::ref_ptr<osg::Node>B25 = osgDB::readNodeFile("Models//B25//B25.IVE");
55 
56     osg::ref_ptr < osg::MatrixTransform> scale = new osg::MatrixTransform ;
57     scale ->setMatrix(osg::Matrix::scale(0.1, 0.1, 0.1)*osg::Matrix::translate(-10.0f, -250.0f, 99.0f)) ;
58     scale ->addChild(B25.get()) ;
59 
60     // 添加到场景
61     root->addChild(node.get());
62     root->addChild(scale.get());
63     //root->addChild(B25.get());
64 
65     // 优化场景数据
66     osgUtil::Optimizer optimizer;
67     optimizer.optimize(root.get());
68 
69     viewer->setSceneData(root.get());
70 
71     viewer->realize();
72 
73     viewer->run();
74 
75     return 0;
76     
77 }
 1 #pragma once
 2 
 3 #include <osgViewer/Viewer>
 4 
 5 #include <osg/LineSegment>
 6 #include <osg/Point>
 7 #include <osg/Geometry>
 8 #include <osg/Node>
 9 #include <osg/Geode>
10 #include <osg/Group>
11 
12 #include <osgGA/MatrixManipulator>
13 
14 #include <osgUtil/IntersectVisitor>
15 
16 #include <vector>
17 
18 class TravelManipulator:public osgGA::MatrixManipulator
19 {
20 
21 public:
22 
23     TravelManipulator(void);
24     ~TravelManipulator(void);
25 
26     // 把漫游器添加到场景中
27     static TravelManipulator * TravelToScence(osg::ref_ptr<osgViewer::Viewer>viewer);
28 
29 private:
30 
31     osg::ref_ptr<osgViewer::Viewer>m_pHostViewer;
32 
33     // 移动速度
34     float m_fMoveSpeed;
35 
36     // 当前位置
37     osg::Vec3 m_vPosition;
38 
39     // 旋转角度
40     osg::Vec3 m_vRotation;
41 
42 public:
43 
44     // 鼠标左键状态
45     bool m_bLeftButtonDown;
46 
47     // 鼠标位置
48     float m_fpushX;
49     float m_fpushY;
50 
51     // 设置矩阵
52     virtual void setByMatrix(const osg::Matrix &matrix);
53 
54     // 设置逆矩阵
55     virtual void setByInverseMatrix(const osg::Matrix &matrix);
56 
57     // 获取矩阵
58     virtual osg::Matrixd getMatrix() const;
59 
60     // 获取逆矩阵
61     virtual osg::Matrixd getInverseMatrix() const;
62 
63     // 事件处理函数
64     virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us);
65 
66     // 屏幕角度
67     float m_fAngle;
68 
69     // 位置变换
70     void ChangePosition(osg::Vec3 &delta);
71 
72     // 碰撞检测状态
73     bool m_bPeng;
74 
75     // 设置速度
76     float getSpeed();
77 
78     void setSpeed(float &);
79 
80     // 设置初始位置
81     void SetPosition(osg::Vec3 &position);
82 
83     osg::Vec3 GetPosition();
84 
85 
86 };
  1 #include "TravelManipulator.h"
  2 
  3 // 构造函数
  4 TravelManipulator::TravelManipulator():m_fMoveSpeed(1.0f),
  5                                       m_bLeftButtonDown(false),
  6                                       m_fpushX(0),
  7                                       m_fAngle(2.5),
  8                                       m_bPeng(true),
  9                                       m_fpushY(0)
 10 {
 11     m_vPosition = osg::Vec3(-22.0f, -274.0f, 100.0f);
 12     m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f);
 13 }
 14 
 15 TravelManipulator::~TravelManipulator(void)
 16 {
 17 }
 18 
 19 // 把漫游器添加到场景中
 20 TravelManipulator *TravelManipulator::TravelToScence(osg::ref_ptr<osgViewer::Viewer> viewer)
 21 {
 22     TravelManipulator* camera = new TravelManipulator;
 23 
 24     viewer->setCameraManipulator(camera);
 25 
 26     camera->m_pHostViewer = viewer;
 27 
 28     return camera;
 29 }
 30 
 31 // 设置矩阵
 32 void TravelManipulator::setByMatrix(const osg::Matrix &matrix)
 33 {
 34 
 35 }
 36 
 37 // 设置逆矩阵
 38 void TravelManipulator::setByInverseMatrix(const osg::Matrix &matrix)
 39 {
 40 
 41 }
 42 
 43 // 得到矩阵
 44 osg::Matrixd TravelManipulator::getMatrix(void)const
 45 {
 46     osg::Matrixd mat;
 47 
 48     mat.makeRotate(m_vRotation._v[0], osg::Vec3(1.0f, 0.0f, 0.0f),
 49                    m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f),
 50                    m_vRotation._v[2], osg::Vec3(0.0f, 0.0f, 1.0f));
 51 
 52     return mat * osg::Matrixd::translate(m_vPosition);
 53                                       
 54 }
 55 
 56 // 得到逆矩阵
 57 osg::Matrixd TravelManipulator::getInverseMatrix(void) const
 58 {
 59     osg::Matrixd mat;
 60 
 61     mat.makeRotate(m_vRotation._v[0], osg::Vec3(1.0f, 0.0f, 0.0f),
 62         m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f),
 63         m_vRotation._v[2], osg::Vec3(0.0f, 0.0f, 1.0f));
 64 
 65     return osg::Matrixd::inverse(mat * osg::Matrixd::translate(m_vPosition));
 66 }
 67 
 68 // 事件处理函数
 69 bool TravelManipulator::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us)
 70 {
 71     // 获取鼠标位置
 72     float mouseX = ea.getX();
 73     float mouseY = ea.getY();
 74 
 75     switch(ea.getEventType())
 76     {
 77     case(osgGA::GUIEventAdapter::KEYDOWN):
 78         {
 79             // 空格键
 80             if(ea.getKey() == 0x20)
 81             {
 82                 us.requestRedraw();
 83                 us.requestContinuousUpdate(false);
 84 
 85                 return true;
 86 
 87             }
 88 
 89             // 上移键
 90             if (ea.getKey() == 0xFF50)
 91             {
 92                 ChangePosition(osg::Vec3(0, 0, m_fMoveSpeed));
 93 
 94                 return true;
 95             }
 96 
 97             // 下移键
 98             if (ea.getKey() == 0xFF57)
 99             {
100                 ChangePosition(osg::Vec3(0, 0, -m_fMoveSpeed));
101 
102                 return true;
103             }
104 
105             // 加速
106             if (ea.getKey() == 0x2B)
107             {
108                 m_fMoveSpeed += 1.0f;
109 
110                 return true;
111             }
112 
113             // 减少速度
114             if (ea.getKey() == 0x2D)
115             {
116                 m_fMoveSpeed -= 0.1f;
117 
118                 if(m_fMoveSpeed < 1.0f)
119                 {
120                     m_fMoveSpeed = 1.0f;
121                 }
122 
123                 return true;
124             }
125 
126             // 前进
127             if (ea.getKey() == 0xFF52 || ea.getKey() == 0x57 || ea.getKey() == 0x77)
128             {
129                 ChangePosition(osg::Vec3(0, m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[2]), 0));
130                 ChangePosition(osg::Vec3(m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[2]),0,0));
131 
132                 return true;
133             }
134 
135             // 后退
136             if (ea.getKey() == 0xFF54 || ea.getKey() == 0x53 || ea.getKey() == 0x73)
137             {
138                 ChangePosition(osg::Vec3(0, -m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[2]), 0));
139                 ChangePosition(osg::Vec3(-m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[2]),0,0));
140 
141                 return true;
142             }
143 
144             // 向左
145             if (ea.getKey() == 0x41 || ea.getKey() == 0x61)
146             {
147                 ChangePosition(osg::Vec3(0, m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[2]),0));
148                 ChangePosition(osg::Vec3(-m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[2]),0,0));
149 
150                 return true;
151             }
152             
153             // 向右
154             if (ea.getKey() == 0x44 || ea.getKey() == 0x64)
155             {
156                 ChangePosition(osg::Vec3(0, -m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[2]),0));
157                 ChangePosition(osg::Vec3(m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[2]),0,0));
158 
159                 return true;
160             }
161 
162             // 向右转
163             if (ea.getKey() == 0xFF53)
164             {
165                 m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle);
166             }
167 
168             // 向左转
169             if (ea.getKey() == 0xFF51)
170             {
171                 m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle);
172             }
173 
174             // 改变屏幕角度F键
175             if (ea.getKey() == 0x46 || ea.getKey() == 0x66)
176             {
177                 m_fAngle -= 0.2;
178 
179                 return true;
180             }
181 
182             //G键
183             if (ea.getKey() == 0x47 || ea.getKey() == 0x66)
184             {
185                 m_fAngle += 0.2;
186 
187                 return true;
188             }
189 
190             return true;
191     }
192         case(osgGA::GUIEventAdapter::PUSH):
193 
194         if (ea.getButton() == 1)
195         {
196             m_fpushX = mouseX;
197             m_fpushY = mouseY;
198 
199             m_bLeftButtonDown = true;
200         }
201 
202         return true;
203 
204         // 拖动
205     case(osgGA::GUIEventAdapter::DRAG):
206 
207         if (m_bLeftButtonDown)
208         {
209             m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle * (mouseX - m_fpushX)) / 200;
210             m_vRotation._v[0] += osg::DegreesToRadians(1.1 * (mouseY - m_fpushY)) / 200;
211 
212             if (m_vRotation._v[0] >= 3.14)
213             {
214                 m_vRotation._v[0] = 3.14;
215             }
216 
217             if (m_vRotation._v[0] <= 0)
218             {
219                 m_vRotation._v[0] = 0;
220             }
221         }
222 
223         return false;
224 
225         // 鼠标释放
226     case(osgGA::GUIEventAdapter::RELEASE):
227 
228         if (ea.getButton() == 1)
229         {
230             m_bLeftButtonDown = false;
231         }
232 
233         return false;
234 
235     default:
236 
237         return false;
238 }
239 
240 }
241 
242 // 位置变换函数
243 void TravelManipulator::ChangePosition(osg::Vec3 &delta)
244 {
245     // 碰撞检测
246     if (m_bPeng)
247     {
248         // 得到新的位置
249         osg::Vec3 newPos1 = m_vPosition + delta;
250 
251         osgUtil::IntersectVisitor ivXY;
252 
253         // 根据新的位置得到两条线段检测
254         osg::ref_ptr<osg::LineSegment>lineXY = new osg::LineSegment(newPos1, m_vPosition);
255 
256         osg::ref_ptr<osg::LineSegment>lineZ = new osg::LineSegment(newPos1 + osg::Vec3(0.0f, 0.0f, 10.0f), newPos1 - osg::Vec3(0.0f, 0.0f, -10.0f));
257 
258         ivXY.addLineSegment(lineZ.get());
259         ivXY.addLineSegment(lineXY.get());
260 
261         // 结构交集检测
262         m_pHostViewer->getSceneData()->accept(ivXY);
263 
264         // 如果没有碰撞
265         if (!ivXY.hits())
266         {
267             m_vPosition += delta;
268         }
269 
270     }
271     else
272     {
273         m_vPosition += delta;
274     }
275 }
276 
277 // 设置速度
278 void TravelManipulator::setSpeed(float &sp)
279 {
280     m_fMoveSpeed = sp;
281 }
282 
283 // 获得当前速度
284 float TravelManipulator::getSpeed()
285 {
286     return m_fMoveSpeed;
287 }
288 
289 // 设置起始的位置
290 void TravelManipulator::SetPosition(osg::Vec3 &position)
291 {
292     m_vPosition = position;
293 }
294 
295 // 得到当前所在位置
296 osg::Vec3 TravelManipulator::GetPosition()
297 {
298     return m_vPosition;
299 }

 

 

OSG实现场景漫游(转载)

标签:

原文地址:http://www.cnblogs.com/Vae1990Silence/p/5782175.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!