1 // Copyright (C) 2009 - 2012  Mathias Froehlich
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20 
21 #include "HLACameraManipulator.hxx"
22 
23 #include <simgear/scene/util/OsgMath.hxx>
24 #include "HLAPerspectiveViewer.hxx"
25 #include "Viewer.hxx"
26 
27 namespace fgviewer  {
28 
HLACameraManipulator(HLAPerspectiveViewer * perspectiveViewer)29 HLACameraManipulator::HLACameraManipulator(HLAPerspectiveViewer* perspectiveViewer) :
30     _viewMatrix(osg::Matrixd::identity()),
31     _inverseViewMatrix(osg::Matrixd::identity()),
32     _lastMousePos(0, 0),
33     _perspectiveViewer(perspectiveViewer)
34 {
35 }
36 
HLACameraManipulator(const HLACameraManipulator & cameraManipulator,const osg::CopyOp & copyOp)37 HLACameraManipulator::HLACameraManipulator(const HLACameraManipulator& cameraManipulator, const osg::CopyOp& copyOp) :
38     osgGA::CameraManipulator(cameraManipulator, copyOp),
39     _viewMatrix(cameraManipulator._viewMatrix),
40     _inverseViewMatrix(cameraManipulator._inverseViewMatrix),
41     _lastMousePos(cameraManipulator._lastMousePos),
42     _perspectiveViewer(cameraManipulator._perspectiveViewer)
43 {
44 }
45 
~HLACameraManipulator()46 HLACameraManipulator::~HLACameraManipulator()
47 {
48 }
49 
50 void
setByMatrix(const osg::Matrixd & matrix)51 HLACameraManipulator::setByMatrix(const osg::Matrixd& matrix)
52 {
53 }
54 
55 void
setByInverseMatrix(const osg::Matrixd & matrix)56 HLACameraManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
57 {
58 }
59 
60 osg::Matrixd
getMatrix() const61 HLACameraManipulator::getMatrix() const
62 {
63     return _viewMatrix;
64 }
65 
66 osg::Matrixd
getInverseMatrix() const67 HLACameraManipulator::getInverseMatrix() const
68 {
69     return _inverseViewMatrix;
70 }
71 
72 bool
handle(const osgGA::GUIEventAdapter & eventAdapter,osgGA::GUIActionAdapter & actionAdapter)73 HLACameraManipulator::handle(const osgGA::GUIEventAdapter& eventAdapter, osgGA::GUIActionAdapter& actionAdapter)
74 {
75     if (_handle(eventAdapter, static_cast<Viewer&>(actionAdapter)))
76         return true;
77     return osgGA::CameraManipulator::handle(eventAdapter, actionAdapter);
78 }
79 
80 bool
_handle(const osgGA::GUIEventAdapter & eventAdapter,Viewer & viewer)81 HLACameraManipulator::_handle(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
82 {
83     switch (eventAdapter.getEventType()) {
84     case osgGA::GUIEventAdapter::PUSH:
85         _lastMousePos = osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized());
86         break;
87     case osgGA::GUIEventAdapter::RELEASE:
88         break;
89     case osgGA::GUIEventAdapter::DOUBLECLICK:
90         break;
91     case osgGA::GUIEventAdapter::DRAG:
92         if (!eventAdapter.getModKeyMask())
93             _rotateView(osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized()) - _lastMousePos);
94         else if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL)
95             _rotateSun(osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized()) - _lastMousePos, viewer);
96         _lastMousePos = osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized());
97         break;
98     case osgGA::GUIEventAdapter::MOVE:
99         break;
100     case osgGA::GUIEventAdapter::SCROLL:
101         break;
102 
103     case osgGA::GUIEventAdapter::KEYDOWN:
104         _handleKeyDownEvent(eventAdapter, viewer);
105         break;
106     case osgGA::GUIEventAdapter::KEYUP:
107         _handleKeyUpEvent(eventAdapter, viewer);
108         break;
109 
110     case osgGA::GUIEventAdapter::FRAME:
111         _handleFrameEvent(viewer);
112         break;
113 
114     default:
115         break;
116     }
117     return false;
118 }
119 
120 void
_handleFrameEvent(osgGA::GUIActionAdapter & actionAdapter)121 HLACameraManipulator::_handleFrameEvent(osgGA::GUIActionAdapter& actionAdapter)
122 {
123     // Note that eventAdapter.getTime() returns the reference time instead of the simulation time
124     osg::View* view = actionAdapter.asView();
125     if (!view)
126         return;
127     osg::FrameStamp* frameStamp = view->getFrameStamp();
128     if (!frameStamp)
129         return;
130     if (!_perspectiveViewer.valid())
131         return;
132 
133     SGLocationd location;
134     location = _perspectiveViewer->getLocation(SGTimeStamp::fromSec(frameStamp->getSimulationTime()));
135 
136     // Update the main cameras view matrix
137     _viewMatrix = osg::Matrixd::identity();
138     // transform from the simulation typical x-forward/y-right/z-down
139     // to the opengl camera system x-right/y-up/z-back
140     // _viewMatrix.postMultRotate(toOsg(SGQuatd::fromEulerDeg(90, 0, -90)));
141     _viewMatrix.postMultRotate(toOsg(SGQuatd(-0.5, -0.5, 0.5, 0.5)));
142     // the orientation of the view
143     _viewMatrix.postMultRotate(toOsg(location.getOrientation()));
144     // the position of the view
145     _viewMatrix.postMultTranslate(toOsg(location.getPosition()));
146     _inverseViewMatrix = osg::Matrixd::inverse(_viewMatrix);
147 }
148 
149 bool
_handleKeyDownEvent(const osgGA::GUIEventAdapter & eventAdapter,Viewer & viewer)150 HLACameraManipulator::_handleKeyDownEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
151 {
152     if (!_perspectiveViewer.valid())
153         return false;
154 
155     switch (eventAdapter.getKey()) {
156     case osgGA::GUIEventAdapter::KEY_Space:
157     case osgGA::GUIEventAdapter::KEY_Home:
158         _resetView();
159         return false;
160 
161     case osgGA::GUIEventAdapter::KEY_Left:
162         _incrementEyePosition(SGVec3d(-0.1, 0, 0));
163         return false;
164     case osgGA::GUIEventAdapter::KEY_Right:
165         _incrementEyePosition(SGVec3d(0.1, 0, 0));
166         return false;
167     case osgGA::GUIEventAdapter::KEY_Up:
168         if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL) {
169             _perspectiveViewer->setZoomFactor(_perspectiveViewer->getZoomFactor()*1.1);
170         } else if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT) {
171             _incrementEyePosition(SGVec3d(0, 0, 0.1));
172         } else {
173             _incrementEyePosition(SGVec3d(0, 0.1, 0));
174         }
175         return false;
176     case osgGA::GUIEventAdapter::KEY_Down:
177         if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL) {
178             _perspectiveViewer->setZoomFactor(_perspectiveViewer->getZoomFactor()/1.1);
179         } else if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT) {
180             _incrementEyePosition(SGVec3d(0, 0, -0.1));
181         } else {
182             _incrementEyePosition(SGVec3d(0, -0.1, 0));
183         }
184         return false;
185     default:
186         return false;
187     }
188 }
189 
190 bool
_handleKeyUpEvent(const osgGA::GUIEventAdapter & eventAdapter,Viewer & viewer)191 HLACameraManipulator::_handleKeyUpEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
192 {
193     return false;
194 }
195 
196 void
_incrementEyePosition(const SGVec3d & offset)197 HLACameraManipulator::_incrementEyePosition(const SGVec3d& offset)
198 {
199     if (!_perspectiveViewer.valid())
200         return;
201     HLAEyeTracker* eyeTracker = _perspectiveViewer->getEyeTracker();
202     if (!eyeTracker)
203         return;
204     eyeTracker->setLeftEyeOffset(eyeTracker->getLeftEyeOffset() + offset);
205     eyeTracker->setRightEyeOffset(eyeTracker->getRightEyeOffset() + offset);
206 }
207 
208 void
_resetView()209 HLACameraManipulator::_resetView()
210 {
211     if (!_perspectiveViewer.valid())
212         return;
213     _perspectiveViewer->setPosition(SGVec3d::zeros());
214     _perspectiveViewer->setOrientation(SGQuatd::unit());
215     _perspectiveViewer->setZoomFactor(1);
216     HLAEyeTracker* eyeTracker = _perspectiveViewer->getEyeTracker();
217     if (!eyeTracker)
218         return;
219     eyeTracker->setLeftEyeOffset(SGVec3d::zeros());
220     eyeTracker->setRightEyeOffset(SGVec3d::zeros());
221 }
222 
223 void
_rotateView(const osg::Vec2 & inc)224 HLACameraManipulator::_rotateView(const osg::Vec2& inc)
225 {
226     if (!_perspectiveViewer.valid())
227         return;
228     double zDeg, yDeg, xDeg;
229     _perspectiveViewer->getOrientation().getEulerRad(zDeg, yDeg, xDeg);
230     zDeg += inc[0];
231     yDeg += inc[1];
232     _perspectiveViewer->setOrientation(SGQuatd::fromEulerRad(zDeg, yDeg, xDeg));
233 }
234 
235 void
_rotateSun(const osg::Vec2 & inc,Viewer & viewer)236 HLACameraManipulator::_rotateSun(const osg::Vec2& inc, Viewer& viewer)
237 {
238     osg::Light* light = viewer.getLight();
239     if (!light)
240         return;
241     osg::Matrix m = osg::Matrix::inverse(viewer.getCamera()->getViewMatrix());
242     osg::Vec3 position(light->getPosition()[0], light->getPosition()[1], light->getPosition()[2]) ;
243     position = osg::Quat(-0.2*inc[0], osg::Matrix::transform3x3(osg::Vec3(0, 1, 0), m))*position;
244     position = osg::Quat(0.2*inc[1], osg::Matrix::transform3x3(osg::Vec3(1, 0, 0), m))*position;
245     light->setPosition(osg::Vec4(position, 0));
246 }
247 
248 } // namespace fgviewer
249