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