1 // Copyright (C) 2009 - 2012 Mathias Froehlich
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.
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.
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.
21 #include "HLACameraManipulator.hxx"
23 #include <simgear/scene/util/OsgMath.hxx>
24 #include "HLAPerspectiveViewer.hxx"
29 HLACameraManipulator::HLACameraManipulator(HLAPerspectiveViewer* perspectiveViewer) :
30 _viewMatrix(osg::Matrixd::identity()),
31 _inverseViewMatrix(osg::Matrixd::identity()),
33 _perspectiveViewer(perspectiveViewer)
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)
46 HLACameraManipulator::~HLACameraManipulator()
51 HLACameraManipulator::setByMatrix(const osg::Matrixd& matrix)
56 HLACameraManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
61 HLACameraManipulator::getMatrix() const
67 HLACameraManipulator::getInverseMatrix() const
69 return _inverseViewMatrix;
73 HLACameraManipulator::handle(const osgGA::GUIEventAdapter& eventAdapter, osgGA::GUIActionAdapter& actionAdapter)
75 if (_handle(eventAdapter, static_cast<Viewer&>(actionAdapter)))
77 return osgGA::CameraManipulator::handle(eventAdapter, actionAdapter);
81 HLACameraManipulator::_handle(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
83 switch (eventAdapter.getEventType()) {
84 case osgGA::GUIEventAdapter::PUSH:
85 _lastMousePos = osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized());
87 case osgGA::GUIEventAdapter::RELEASE:
89 case osgGA::GUIEventAdapter::DOUBLECLICK:
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());
98 case osgGA::GUIEventAdapter::MOVE:
100 case osgGA::GUIEventAdapter::SCROLL:
103 case osgGA::GUIEventAdapter::KEYDOWN:
104 _handleKeyDownEvent(eventAdapter, viewer);
106 case osgGA::GUIEventAdapter::KEYUP:
107 _handleKeyUpEvent(eventAdapter, viewer);
110 case osgGA::GUIEventAdapter::FRAME:
111 _handleFrameEvent(viewer);
121 HLACameraManipulator::_handleFrameEvent(osgGA::GUIActionAdapter& actionAdapter)
123 // Note that eventAdapter.getTime() returns the reference time instead of the simulation time
124 osg::View* view = actionAdapter.asView();
127 osg::FrameStamp* frameStamp = view->getFrameStamp();
130 if (!_perspectiveViewer.valid())
133 SGLocationd location;
134 location = _perspectiveViewer->getLocation(SGTimeStamp::fromSec(frameStamp->getSimulationTime()));
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);
150 HLACameraManipulator::_handleKeyDownEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
152 if (!_perspectiveViewer.valid())
155 switch (eventAdapter.getKey()) {
156 case osgGA::GUIEventAdapter::KEY_Space:
157 case osgGA::GUIEventAdapter::KEY_Home:
161 case osgGA::GUIEventAdapter::KEY_Left:
162 _incrementEyePosition(SGVec3d(-0.1, 0, 0));
164 case osgGA::GUIEventAdapter::KEY_Right:
165 _incrementEyePosition(SGVec3d(0.1, 0, 0));
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));
173 _incrementEyePosition(SGVec3d(0, 0.1, 0));
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));
182 _incrementEyePosition(SGVec3d(0, -0.1, 0));
191 HLACameraManipulator::_handleKeyUpEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
197 HLACameraManipulator::_incrementEyePosition(const SGVec3d& offset)
199 if (!_perspectiveViewer.valid())
201 HLAEyeTracker* eyeTracker = _perspectiveViewer->getEyeTracker();
204 eyeTracker->setLeftEyeOffset(eyeTracker->getLeftEyeOffset() + offset);
205 eyeTracker->setRightEyeOffset(eyeTracker->getRightEyeOffset() + offset);
209 HLACameraManipulator::_resetView()
211 if (!_perspectiveViewer.valid())
213 _perspectiveViewer->setPosition(SGVec3d::zeros());
214 _perspectiveViewer->setOrientation(SGQuatd::unit());
215 _perspectiveViewer->setZoomFactor(1);
216 HLAEyeTracker* eyeTracker = _perspectiveViewer->getEyeTracker();
219 eyeTracker->setLeftEyeOffset(SGVec3d::zeros());
220 eyeTracker->setRightEyeOffset(SGVec3d::zeros());
224 HLACameraManipulator::_rotateView(const osg::Vec2& inc)
226 if (!_perspectiveViewer.valid())
228 double zDeg, yDeg, xDeg;
229 _perspectiveViewer->getOrientation().getEulerRad(zDeg, yDeg, xDeg);
232 _perspectiveViewer->setOrientation(SGQuatd::fromEulerRad(zDeg, yDeg, xDeg));
236 HLACameraManipulator::_rotateSun(const osg::Vec2& inc, Viewer& viewer)
238 osg::Light* light = viewer.getLight();
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));
248 } // namespace fgviewer